|
root / base / usr / src / uts / common / sys / ddi_impldefs.h
ddi_impldefs.h C 1279 lines 41.8 KB
   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
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 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
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 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
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2012 Garrett D'Amore <garrett@damore.org>.  All rights reserved.
 * Copyright 2016 Joyent, Inc.
 * Copyright (c) 2016 by Delphix. All rights reserved.
 * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
 */

#ifndef _SYS_DDI_IMPLDEFS_H
#define	_SYS_DDI_IMPLDEFS_H

#include <sys/types.h>
#include <sys/param.h>
#include <sys/t_lock.h>
#include <sys/ddipropdefs.h>
#include <sys/devops.h>
#include <sys/autoconf.h>
#include <sys/mutex.h>
#include <vm/page.h>
#include <sys/dacf_impl.h>
#include <sys/ndifm.h>
#include <sys/epm.h>
#include <sys/ddidmareq.h>
#include <sys/ddi_intr.h>
#include <sys/ddi_hp.h>
#include <sys/ddi_hp_impl.h>
#include <sys/ddi_isa.h>
#include <sys/id_space.h>
#include <sys/modhash.h>
#include <sys/bitset.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * The device id implementation has been switched to be based on properties.
 * For compatibility with di_devid libdevinfo interface the following
 * must be defined:
 */
#define	DEVID_COMPATIBILITY	((ddi_devid_t)-1)

/*
 * Definitions for node class.
 * DDI_NC_PROM: a node with a nodeid that may be used in a promif call.
 * DDI_NC_PSEUDO: a software created node with a software assigned nodeid.
 */
typedef enum {
	DDI_NC_PROM = 0,
	DDI_NC_PSEUDO
} ddi_node_class_t;

/*
 * Definitions for generic callback mechanism.
 */
typedef enum {
	DDI_CB_INTR_ADD,		/* More available interrupts */
	DDI_CB_INTR_REMOVE		/* Fewer available interrupts */
} ddi_cb_action_t;

typedef enum {
	DDI_CB_FLAG_INTR = 0x1		/* Driver is IRM aware */
} ddi_cb_flags_t;

#define	DDI_CB_FLAG_VALID(f)	((f) & DDI_CB_FLAG_INTR)

typedef int	(*ddi_cb_func_t)(dev_info_t *dip, ddi_cb_action_t action,
		    void *cbarg, void *arg1, void *arg2);

typedef struct ddi_cb {
	uint64_t	cb_flags;
	dev_info_t	*cb_dip;
	ddi_cb_func_t	cb_func;
	void		*cb_arg1;
	void		*cb_arg2;
} ddi_cb_t;

/*
 * dev_info:	The main device information structure this is intended to be
 *		opaque to drivers and drivers should use ddi functions to
 *		access *all* driver accessible fields.
 *
 * devi_parent_data includes property lists (interrupts, registers, etc.)
 * devi_driver_data includes whatever the driver wants to place there.
 */
struct devinfo_audit;

typedef struct devi_port {
	union {
		struct {
			uint32_t type;
			uint32_t pad;
		} port;
		uint64_t type64;
	} info;
	void	*priv_p;
} devi_port_t;

typedef struct devi_bus_priv {
	devi_port_t port_up;
	devi_port_t port_down;
} devi_bus_priv_t;

#if defined(__x86)
struct iommulib_unit;
typedef struct iommulib_unit *iommulib_handle_t;
struct iommulib_nex;
typedef struct iommulib_nex *iommulib_nexhandle_t;
#endif

typedef uint8_t	ndi_flavor_t;
struct ddi_hp_cn_handle;

struct in_node;

struct dev_info  {

	struct dev_info *devi_parent;	/* my parent node in tree	*/
	struct dev_info *devi_child;	/* my child list head		*/
	struct dev_info *devi_sibling;	/* next element on my level	*/

	char	*devi_binding_name;	/* name used to bind driver:	*/
					/* shared storage, points to	*/
					/* devi_node_name, devi_compat_names */
					/* or devi_rebinding_name	*/

	char	*devi_addr;		/* address part of name		*/

	int	devi_nodeid;		/* device nodeid		*/
	int	devi_instance;		/* device instance number	*/

	struct dev_ops *devi_ops;	/* driver operations		*/

	void	*devi_parent_data;	/* parent private data		*/
	void	*devi_driver_data;	/* driver private data		*/

	ddi_prop_t *devi_drv_prop_ptr;	/* head of driver prop list */
	ddi_prop_t *devi_sys_prop_ptr;	/* head of system prop list */

	struct ddi_minor_data *devi_minor;	/* head of minor list */
	struct dev_info *devi_next;	/* Next instance of this device */
	kmutex_t devi_lock;		/* Protects per-devinfo data */

	/* logical parents for busop primitives */

	struct dev_info *devi_bus_map_fault;	/* bus_map_fault parent	 */
	void		*devi_obsolete;		/* obsolete placeholder */
	struct dev_info *devi_bus_dma_allochdl; /* bus_dma_newhdl parent */
	struct dev_info *devi_bus_dma_freehdl;  /* bus_dma_freehdl parent */
	struct dev_info *devi_bus_dma_bindhdl;  /* bus_dma_bindhdl parent */
	struct dev_info *devi_bus_dma_unbindhdl; /* bus_dma_unbindhdl parent */
	struct dev_info *devi_bus_dma_flush;    /* bus_dma_flush parent	 */
	struct dev_info *devi_bus_dma_win;	/* bus_dma_win parent	 */
	struct dev_info *devi_bus_dma_ctl;	/* bus_dma_ctl parent	 */
	struct dev_info	*devi_bus_ctl;		/* bus_ctl parent	 */

	ddi_prop_t *devi_hw_prop_ptr;		/* head of hw prop list */

	char	*devi_node_name;		/* The 'name' of the node */
	char	*devi_compat_names;		/* A list of driver names */
	size_t	devi_compat_length;		/* Size of compat_names */

	int (*devi_bus_dma_bindfunc)(dev_info_t *, dev_info_t *,
	    ddi_dma_handle_t, struct ddi_dma_req *, ddi_dma_cookie_t *,
	    uint_t *);
	int (*devi_bus_dma_unbindfunc)(dev_info_t *, dev_info_t *,
	    ddi_dma_handle_t);

	char		*devi_devid_str;	/* registered device id */

	/*
	 * power management entries
	 * components exist even if the device is not currently power managed
	 */
	struct pm_info *devi_pm_info;		/* 0 => dev not power managed */
	uint_t		devi_pm_flags;		/* pm flags */
	int		devi_pm_num_components;	/* number of components */
	size_t		devi_pm_comp_size;	/* size of devi_components */
	struct pm_component *devi_pm_components; /* array of pm components */
	struct dev_info *devi_pm_ppm;		/* ppm attached to this one */
	void		*devi_pm_ppm_private;	/* for use by ppm driver */
	int		devi_pm_dev_thresh;	/* "device" threshold */
	uint_t		devi_pm_kidsupcnt;	/* # of kids powered up */
	struct pm_scan	*devi_pm_scan;		/* pm scan info */
	uint_t		devi_pm_noinvolpm;	/* # of descendents no-invol */
	uint_t		devi_pm_volpmd;		/* # of voluntarily pm'ed */
	kmutex_t	devi_pm_lock;		/* pm lock for state */
	kmutex_t	devi_pm_busy_lock;	/* for component busy count */

	uint_t		devi_state;		/* device/bus state flags */
						/* see below for definitions */
	kcondvar_t	devi_cv;		/* cv */
	int		devi_ref;		/* reference count */

	dacf_rsrvlist_t *devi_dacf_tasks;	/* dacf reservation queue */

	ddi_node_class_t devi_node_class;	/* Node class */
	int		devi_node_attributes;	/* Node attributes: See below */

	char		*devi_device_class;

	/*
	 * New mpxio kernel hooks entries
	 */
	int		devi_mdi_component;	/* mpxio component type */
	void		*devi_mdi_client;	/* mpxio client information */
	void		*devi_mdi_xhci;		/* vhci/phci info */

	ddi_prop_list_t	*devi_global_prop_list;	/* driver global properties */
	major_t		devi_major;		/* driver major number */
	ddi_node_state_t devi_node_state;	/* state of node */
	uint_t		devi_flags;		/* configuration flags */
	int		devi_circular;		/* for recursive operations */
	void		*devi_busy_thread;	/* thread operating on node */
	void		*devi_taskq;		/* hotplug taskq */

	/* device driver statistical and audit info */
	struct devinfo_audit *devi_audit;		/* last state change */

	/*
	 * FMA support for resource caches and error handlers
	 */
	struct i_ddi_fmhdl	*devi_fmhdl;

	uint_t		devi_cpr_flags;

	/* Owned by DDI interrupt framework */
	devinfo_intr_t	*devi_intr_p;

	void		*devi_nex_pm;		/* nexus PM private */

	char		*devi_addr_buf;		/* buffer for devi_addr */

	char		*devi_rebinding_name;	/* binding_name of rebind */

	/* For device contracts that have this dip's minor node as resource */
	kmutex_t	devi_ct_lock;		/* contract lock */
	kcondvar_t	devi_ct_cv;		/* contract cv */
	int		devi_ct_count;		/* # of outstanding responses */
	int		devi_ct_neg;		/* neg. occurred on dip */
	list_t		devi_ct;

	/* owned by bus framework */
	devi_bus_priv_t	devi_bus;		/* bus private data */

	/* Declarations of the pure dynamic properties to snapshot */
	struct i_ddi_prop_dyn	*devi_prop_dyn_driver;	/* prop_op */
	struct i_ddi_prop_dyn	*devi_prop_dyn_parent;	/* bus_prop_op */

#if defined(__x86)
	/* For x86 (Intel and AMD) IOMMU support */
	void		*devi_iommu;
	iommulib_handle_t	devi_iommulib_handle;
	iommulib_nexhandle_t	devi_iommulib_nex_handle;
#endif

	/* Generic callback mechanism */
	ddi_cb_t	*devi_cb_p;

	/* ndi 'flavors' */
	ndi_flavor_t	devi_flavor;		/* flavor assigned by parent */
	ndi_flavor_t	devi_flavorv_n;		/* number of child-flavors */
	void		**devi_flavorv;		/* child-flavor specific data */

	/* Owned by hotplug framework */
	struct ddi_hp_cn_handle *devi_hp_hdlp;   /* hotplug handle list */

	struct in_node  *devi_in_node; /* pointer to devinfo node's in_node_t */

	/* detach event data */
	char	*devi_ev_path;
	int	devi_ev_instance;

	/*
	 * Unbind callback data.
	 */
	kmutex_t	devi_unbind_lock;
	list_t		devi_unbind_cbs;
};

#define	DEVI(dev_info_type)	((struct dev_info *)(dev_info_type))

/*
 * NB: The 'name' field, for compatibility with old code (both existing
 * device drivers and userland code), is now defined as the name used
 * to bind the node to a device driver, and not the device node name.
 * If the device node name does not define a binding to a device driver,
 * and the framework uses a different algorithm to create the binding to
 * the driver, the node name and binding name will be different.
 *
 * Note that this implies that the node name plus instance number does
 * NOT create a unique driver id; only the binding name plus instance
 * number creates a unique driver id.
 *
 * New code should not use 'devi_name'; use 'devi_binding_name' or
 * 'devi_node_name' and/or the routines that access those fields.
 */

#define	devi_name devi_binding_name

/*
 * DDI_CF1, DDI_CF2 and DDI_DRV_UNLOADED are obsolete. They are kept
 * around to allow legacy drivers to to compile.
 */
#define	DDI_CF1(devi)		(DEVI(devi)->devi_addr != NULL)
#define	DDI_CF2(devi)		(DEVI(devi)->devi_ops != NULL)
#define	DDI_DRV_UNLOADED(devi)	(DEVI(devi)->devi_ops == &mod_nodev_ops)

/*
 * The device state flags (devi_state) contains information regarding
 * the state of the device (Online/Offline/Down).  For bus nexus
 * devices, the device state also contains state information regarding
 * the state of the bus represented by this nexus node.
 *
 * Device state information is stored in bits [0-7], bus state in bits
 * [8-15].
 *
 * NOTE: all devi_state updates should be protected by devi_lock.
 */
#define	DEVI_DEVICE_OFFLINE	0x00000001
#define	DEVI_DEVICE_DOWN	0x00000002
#define	DEVI_DEVICE_DEGRADED	0x00000004
#define	DEVI_DEVICE_REMOVED	0x00000008 /* hardware removed */

#define	DEVI_BUS_QUIESCED	0x00000100
#define	DEVI_BUS_DOWN		0x00000200
#define	DEVI_NDI_CONFIG		0x00000400 /* perform config when attaching */

#define	DEVI_S_ATTACHING	0x00010000
#define	DEVI_S_DETACHING	0x00020000
#define	DEVI_S_ONLINING		0x00040000
#define	DEVI_S_OFFLINING	0x00080000

#define	DEVI_S_INVOKING_DACF	0x00100000 /* busy invoking a dacf task */

#define	DEVI_S_UNBOUND		0x00200000
#define	DEVI_S_REPORT		0x08000000 /* report status change */

#define	DEVI_S_EVADD		0x10000000 /* state of devfs event */
#define	DEVI_S_EVREMOVE		0x20000000 /* state of devfs event */
#define	DEVI_S_NEED_RESET	0x40000000 /* devo_reset should be called */

/*
 * Device state macros.
 * o All SET/CLR/DONE users must protect context with devi_lock.
 * o DEVI_SET_DEVICE_ONLINE users must do their own DEVI_SET_REPORT.
 * o DEVI_SET_DEVICE_{DOWN|DEGRADED|UP} should only be used when !OFFLINE.
 * o DEVI_SET_DEVICE_UP clears DOWN and DEGRADED.
 */
#define	DEVI_IS_DEVICE_OFFLINE(dip)					\
	((DEVI(dip)->devi_state & DEVI_DEVICE_OFFLINE) == DEVI_DEVICE_OFFLINE)

#define	DEVI_SET_DEVICE_ONLINE(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	if (DEVI(dip)->devi_state & DEVI_DEVICE_DEGRADED) {		\
		mutex_exit(&DEVI(dip)->devi_lock);			\
		e_ddi_undegrade_finalize(dip);				\
		mutex_enter(&DEVI(dip)->devi_lock);			\
	}								\
	/* setting ONLINE clears DOWN, DEGRADED, OFFLINE */		\
	DEVI(dip)->devi_state &= ~(DEVI_DEVICE_DOWN |			\
	    DEVI_DEVICE_DEGRADED | DEVI_DEVICE_OFFLINE);		\
	}

#define	DEVI_SET_DEVICE_OFFLINE(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= (DEVI_DEVICE_OFFLINE | DEVI_S_REPORT);	\
	}

#define	DEVI_IS_DEVICE_DOWN(dip)					\
	((DEVI(dip)->devi_state & DEVI_DEVICE_DOWN) == DEVI_DEVICE_DOWN)

#define	DEVI_SET_DEVICE_DOWN(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	ASSERT(!DEVI_IS_DEVICE_OFFLINE(dip));				\
	DEVI(dip)->devi_state |= (DEVI_DEVICE_DOWN | DEVI_S_REPORT);	\
	}

#define	DEVI_IS_DEVICE_DEGRADED(dip)					\
	((DEVI(dip)->devi_state &					\
	    (DEVI_DEVICE_DEGRADED|DEVI_DEVICE_DOWN)) == DEVI_DEVICE_DEGRADED)

#define	DEVI_SET_DEVICE_DEGRADED(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	ASSERT(!DEVI_IS_DEVICE_OFFLINE(dip));				\
	mutex_exit(&DEVI(dip)->devi_lock);				\
	e_ddi_degrade_finalize(dip);					\
	mutex_enter(&DEVI(dip)->devi_lock);				\
	DEVI(dip)->devi_state |= (DEVI_DEVICE_DEGRADED | DEVI_S_REPORT); \
	}

#define	DEVI_SET_DEVICE_UP(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	ASSERT(!DEVI_IS_DEVICE_OFFLINE(dip));				\
	if (DEVI(dip)->devi_state & DEVI_DEVICE_DEGRADED) {		\
		mutex_exit(&DEVI(dip)->devi_lock);			\
		e_ddi_undegrade_finalize(dip);				\
		mutex_enter(&DEVI(dip)->devi_lock);			\
	}								\
	DEVI(dip)->devi_state &= ~(DEVI_DEVICE_DEGRADED | DEVI_DEVICE_DOWN); \
	DEVI(dip)->devi_state |= DEVI_S_REPORT;				\
	}

/* Device removal and insertion */
#define	DEVI_IS_DEVICE_REMOVED(dip)					\
	((DEVI(dip)->devi_state & DEVI_DEVICE_REMOVED) == DEVI_DEVICE_REMOVED)

#define	DEVI_SET_DEVICE_REMOVED(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_DEVICE_REMOVED | DEVI_S_REPORT;	\
	}

#define	DEVI_SET_DEVICE_REINSERTED(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_DEVICE_REMOVED;			\
	DEVI(dip)->devi_state |= DEVI_S_REPORT;				\
	}

/* Bus state change macros */
#define	DEVI_IS_BUS_QUIESCED(dip)					\
	((DEVI(dip)->devi_state & DEVI_BUS_QUIESCED) == DEVI_BUS_QUIESCED)

#define	DEVI_SET_BUS_ACTIVE(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_BUS_QUIESCED;			\
	DEVI(dip)->devi_state |= DEVI_S_REPORT;				\
	}

#define	DEVI_SET_BUS_QUIESCE(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= (DEVI_BUS_QUIESCED | DEVI_S_REPORT);	\
	}

#define	DEVI_IS_BUS_DOWN(dip)						\
	((DEVI(dip)->devi_state & DEVI_BUS_DOWN) == DEVI_BUS_DOWN)

#define	DEVI_SET_BUS_UP(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_BUS_DOWN;			\
	DEVI(dip)->devi_state |= DEVI_S_REPORT;				\
	}

#define	DEVI_SET_BUS_DOWN(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= (DEVI_BUS_DOWN | DEVI_S_REPORT);	\
	}

/* Status change report needed */
#define	DEVI_NEED_REPORT(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_REPORT) == DEVI_S_REPORT)

#define	DEVI_SET_REPORT(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_REPORT;				\
	}

#define	DEVI_REPORT_DONE(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_REPORT;			\
	}

/* Do an NDI_CONFIG for its children */
#define	DEVI_NEED_NDI_CONFIG(dip)					\
	((DEVI(dip)->devi_state & DEVI_NDI_CONFIG) == DEVI_NDI_CONFIG)

#define	DEVI_SET_NDI_CONFIG(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_NDI_CONFIG;			\
	}

#define	DEVI_CLR_NDI_CONFIG(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_NDI_CONFIG;			\
	}

/* Attaching or detaching state */
#define	DEVI_IS_ATTACHING(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_ATTACHING) == DEVI_S_ATTACHING)

#define	DEVI_SET_ATTACHING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_ATTACHING;			\
	}

#define	DEVI_CLR_ATTACHING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_ATTACHING;			\
	}

#define	DEVI_IS_DETACHING(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_DETACHING) == DEVI_S_DETACHING)

#define	DEVI_SET_DETACHING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_DETACHING;			\
	}

#define	DEVI_CLR_DETACHING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_DETACHING;			\
	}

/* Onlining or offlining state */
#define	DEVI_IS_ONLINING(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_ONLINING) == DEVI_S_ONLINING)

#define	DEVI_SET_ONLINING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_ONLINING;			\
	}

#define	DEVI_CLR_ONLINING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_ONLINING;			\
	}

#define	DEVI_IS_OFFLINING(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_OFFLINING) == DEVI_S_OFFLINING)

#define	DEVI_SET_OFFLINING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_OFFLINING;			\
	}

#define	DEVI_CLR_OFFLINING(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_OFFLINING;			\
	}

#define	DEVI_IS_IN_RECONFIG(dip)					\
	(DEVI(dip)->devi_state & (DEVI_S_OFFLINING | DEVI_S_ONLINING))

/* Busy invoking a dacf task against this node */
#define	DEVI_IS_INVOKING_DACF(dip)					\
	((DEVI(dip)->devi_state & DEVI_S_INVOKING_DACF) == DEVI_S_INVOKING_DACF)

#define	DEVI_SET_INVOKING_DACF(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_INVOKING_DACF;			\
	}

#define	DEVI_CLR_INVOKING_DACF(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_INVOKING_DACF;			\
	}

/* Events for add/remove */
#define	DEVI_EVADD(dip)							\
	((DEVI(dip)->devi_state & DEVI_S_EVADD) == DEVI_S_EVADD)

#define	DEVI_SET_EVADD(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_EVREMOVE;			\
	DEVI(dip)->devi_state |= DEVI_S_EVADD;				\
	}

#define	DEVI_EVREMOVE(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_EVREMOVE) == DEVI_S_EVREMOVE)

#define	DEVI_SET_EVREMOVE(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_EVADD;				\
	DEVI(dip)->devi_state |= DEVI_S_EVREMOVE;			\
	}

#define	DEVI_SET_EVUNINIT(dip)		{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~(DEVI_S_EVADD | DEVI_S_EVREMOVE);	\
	}

/* Need to call the devo_reset entry point for this device at shutdown */
#define	DEVI_NEED_RESET(dip)						\
	((DEVI(dip)->devi_state & DEVI_S_NEED_RESET) == DEVI_S_NEED_RESET)

#define	DEVI_SET_NEED_RESET(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state |= DEVI_S_NEED_RESET;			\
	}

#define	DEVI_CLR_NEED_RESET(dip)	{				\
	ASSERT(mutex_owned(&DEVI(dip)->devi_lock));			\
	DEVI(dip)->devi_state &= ~DEVI_S_NEED_RESET;			\
	}

/*
 * devi_flags bits
 *
 * NOTE: all devi_state updates should be protected by devi_lock.
 */
#define	DEVI_BUSY		0x00000001 /* busy configuring children */
#define	DEVI_MADE_CHILDREN	0x00000002 /* children made from specs */
#define	DEVI_ATTACHED_CHILDREN	0x00000004 /* attached all existing children */
#define	DEVI_BRANCH_HELD	0x00000008 /* branch rooted at this dip held */
#define	DEVI_NO_BIND		0x00000010 /* prevent driver binding */
#define	DEVI_CACHED_DEVID	0x00000020 /* devid cached in devid cache */
#define	DEVI_PHCI_SIGNALS_VHCI	0x00000040 /* pHCI ndi_devi_exit signals vHCI */
#define	DEVI_REBIND		0x00000080 /* post initchild driver rebind */
#define	DEVI_RETIRED		0x00000100 /* device is retired */
#define	DEVI_RETIRING		0x00000200 /* being evaluated for retire */
#define	DEVI_R_CONSTRAINT	0x00000400 /* constraints have been applied  */
#define	DEVI_R_BLOCKED		0x00000800 /* constraints block retire  */
#define	DEVI_CT_NOP		0x00001000 /* NOP contract event occurred */
#define	DEVI_PCI_DEVICE		0x00002000 /* dip is PCI */

#define	DEVI_BUSY_CHANGING(dip)	(DEVI(dip)->devi_flags & DEVI_BUSY)
#define	DEVI_BUSY_OWNED(dip)	(DEVI_BUSY_CHANGING(dip) &&	\
	((DEVI(dip))->devi_busy_thread == curthread))

#define	DEVI_IS_PCI(dip)	(DEVI(dip)->devi_flags & DEVI_PCI_DEVICE)
#define	DEVI_SET_PCI(dip)	(DEVI(dip)->devi_flags |= (DEVI_PCI_DEVICE))

char	*i_ddi_devi_class(dev_info_t *);
int	i_ddi_set_devi_class(dev_info_t *, const char *, int);

/*
 * This structure represents one piece of bus space occupied by a given
 * device. It is used in an array for devices with multiple address windows.
 */
struct regspec {
	uint_t regspec_bustype;		/* cookie for bus type it's on */
	uint_t regspec_addr;		/* address of reg relative to bus */
	uint_t regspec_size;		/* size of this register set */
};

/*
 * This is a version of the above structure that works for 64-bit mappings and
 * doesn't rely on overloading of fields as is done on SPARC. Eventually the
 * struct regspec should be replaced with this.
 */
struct regspec64 {
	uint64_t regspec_bustype;	/* cookie for bus type it's on */
	uint64_t regspec_addr;		/* address of reg relative to bus */
	uint64_t regspec_size;		/* size of this register set */
};

/*
 * This structure represents one piece of nexus bus space.
 * It is used in an array for nexi with multiple bus spaces
 * to define the childs offsets in the parents bus space.
 */
struct rangespec {
	uint_t rng_cbustype;		/* Child's address, hi order */
	uint_t rng_coffset;		/* Child's address, lo order */
	uint_t rng_bustype;		/* Parent's address, hi order */
	uint_t rng_offset;		/* Parent's address, lo order */
	uint_t rng_size;		/* size of space for this entry */
};

#ifdef _KERNEL

typedef enum {
	DDI_PRE = 0,
	DDI_POST = 1
} ddi_pre_post_t;

/*
 * This structure represents notification of a child attach event
 * These could both be the same if attach/detach commands were in the
 * same name space.
 * Note that the target dip is passed as an arg already.
 */
struct attachspec {
	ddi_attach_cmd_t cmd;	/* type of event */
	ddi_pre_post_t	when;	/* one of DDI_PRE or DDI_POST */
	dev_info_t	*pdip;	/* parent of attaching node */
	int		result;	/* result of attach op (post command only) */
};

/*
 * This structure represents notification of a child detach event
 * Note that the target dip is passed as an arg already.
 */
struct detachspec {
	ddi_detach_cmd_t cmd;	/* type of event */
	ddi_pre_post_t	when;	/* one of DDI_PRE or DDI_POST */
	dev_info_t	*pdip;	/* parent of detaching node */
	int		result;	/* result of detach op (post command only) */
};

#endif /* _KERNEL */

typedef enum {
	DDM_MINOR = 0,
	DDM_ALIAS,
	DDM_DEFAULT,
	DDM_INTERNAL_PATH
} ddi_minor_type;

/* implementation flags for driver specified device access control */
#define	DM_NO_FSPERM	0x1

struct devplcy;

struct ddi_minor {
	char		*name;		/* name of node */
	dev_t		dev;		/* device number */
	int		spec_type;	/* block or char */
	int		flags;		/* access flags */
	const char	*node_type;	/* block, byte, serial, network */
	struct devplcy	*node_priv;	/* privilege for this minor */
	mode_t		priv_mode;	/* default apparent privilege mode */
};

/*
 * devi_node_attributes contains node attributes private to the
 * ddi implementation. As a consumer, do not use these bit definitions
 * directly, use the ndi functions that check for the existence of the
 * specific node attributes.
 *
 * DDI_PERSISTENT indicates a 'persistent' node; one that is not
 * automatically freed by the framework if the driver is unloaded
 * or the driver fails to attach to this node.
 *
 * DDI_AUTO_ASSIGNED_NODEID indicates that the nodeid was auto-assigned
 * by the framework and should be auto-freed if the node is removed.
 *
 * DDI_VHCI_NODE indicates that the node type is VHCI. This flag
 * must be set by ndi_devi_config_vhci() routine only.
 *
 * DDI_HIDDEN_NODE indicates that the node should not show up in snapshots
 * or in /devices.
 *
 * DDI_HOTPLUG_NODE indicates that the node created by nexus hotplug.
 */
#define	DDI_PERSISTENT			0x01
#define	DDI_AUTO_ASSIGNED_NODEID	0x02
#define	DDI_VHCI_NODE			0x04
#define	DDI_HIDDEN_NODE			0x08
#define	DDI_HOTPLUG_NODE		0x10

#define	DEVI_VHCI_NODE(dip)						\
	(DEVI(dip)->devi_node_attributes & DDI_VHCI_NODE)

/*
 * The ddi_minor_data structure gets filled in by ddi_create_minor_node.
 * It then gets attached to the devinfo node as a property.
 */
struct ddi_minor_data {
	struct ddi_minor_data *next;	/* next one in the chain */
	dev_info_t	*dip;		/* pointer to devinfo node */
	ddi_minor_type	type;		/* Following data type */
	struct ddi_minor d_minor;	/* Actual minor node data */
};

#define	ddm_name	d_minor.name
#define	ddm_dev		d_minor.dev
#define	ddm_flags	d_minor.flags
#define	ddm_spec_type	d_minor.spec_type
#define	ddm_node_type	d_minor.node_type
#define	ddm_node_priv	d_minor.node_priv
#define	ddm_priv_mode	d_minor.priv_mode

/*
 * parent private data structure contains register, interrupt, property
 * and range information.
 */
struct ddi_parent_private_data {
	int par_nreg;			/* number of regs */
	struct regspec *par_reg;	/* array of regs */
	int par_nintr;			/* number of interrupts */
	struct intrspec *par_intr;	/* array of possible interrupts */
	int par_nrng;			/* number of ranges */
	struct rangespec *par_rng;	/* array of ranges */
};
#define	DEVI_PD(d)	\
	((struct ddi_parent_private_data *)DEVI((d))->devi_parent_data)

#define	sparc_pd_getnreg(dev)		(DEVI_PD(dev)->par_nreg)
#define	sparc_pd_getnintr(dev)		(DEVI_PD(dev)->par_nintr)
#define	sparc_pd_getnrng(dev)		(DEVI_PD(dev)->par_nrng)
#define	sparc_pd_getreg(dev, n)		(&DEVI_PD(dev)->par_reg[(n)])
#define	sparc_pd_getintr(dev, n)	(&DEVI_PD(dev)->par_intr[(n)])
#define	sparc_pd_getrng(dev, n)		(&DEVI_PD(dev)->par_rng[(n)])

#ifdef _KERNEL
/*
 * This data structure is private to the indexed soft state allocator.
 */
typedef struct i_ddi_soft_state {
	void		**array;	/* the array of pointers */
	kmutex_t	lock;		/* serialize access to this struct */
	size_t		size;		/* how many bytes per state struct */
	size_t		n_items;	/* how many structs herein */
	struct i_ddi_soft_state *next;	/* 'dirty' elements */
} i_ddi_soft_state;

/*
 * This data structure is private to the stringhashed soft state allocator.
 */
typedef struct i_ddi_soft_state_bystr {
	size_t		ss_size;	/* how many bytes per state struct */
	mod_hash_t	*ss_mod_hash;	/* hash implementation */
} i_ddi_soft_state_bystr;

/*
 * This data structure is private to the ddi_strid_* implementation
 */
typedef struct i_ddi_strid {
	size_t		strid_chunksz;
	size_t		strid_spacesz;
	id_space_t	*strid_space;
	mod_hash_t	*strid_byid;
	mod_hash_t	*strid_bystr;
} i_ddi_strid;
#endif /* _KERNEL */

/*
 * Solaris DDI DMA implementation structure and function definitions.
 *
 * Note: no callers of DDI functions must depend upon data structures
 * declared below. They are not guaranteed to remain constant.
 */

/*
 * Implementation DMA mapping structure.
 *
 * The publicly visible ddi_dma_req structure is filled
 * in by a caller that wishes to map a memory object
 * for DMA. Internal to this implementation of the public
 * DDI DMA functions this request structure is put together
 * with bus nexus specific functions that have additional
 * information and constraints as to how to go about doing
 * the requested mapping function
 *
 * In this implementation, some of the information from the
 * original requester is retained throughout the lifetime
 * of the I/O mapping being active.
 */

/*
 * This is the implementation specific description
 * of how we've mapped an object for DMA.
 */
#if defined(__sparc)
typedef struct ddi_dma_impl {
	/*
	 * DMA mapping information
	 */
	ulong_t	dmai_mapping;	/* mapping cookie */

	/*
	 * Size of the current mapping, in bytes.
	 *
	 * Note that this is distinct from the size of the object being mapped
	 * for DVMA. We might have only a portion of the object mapped at any
	 * given point in time.
	 */
	uint_t	dmai_size;

	/*
	 * Offset, in bytes, into object that is currently mapped.
	 */
	off_t	dmai_offset;

	/*
	 * Information gathered from the original DMA mapping
	 * request and saved for the lifetime of the mapping.
	 */
	uint_t		dmai_minxfer;
	uint_t		dmai_burstsizes;
	uint_t		dmai_ndvmapages;
	uint_t		dmai_pool;	/* cached DVMA space */
	uint_t		dmai_rflags;	/* requester's flags + ours */
	uint_t		dmai_inuse;	/* active handle? */
	uint_t		dmai_nwin;
	uint_t		dmai_winsize;
	uint_t		dmai_ncookies;
	uint_t		dmai_curcookie;
	caddr_t		dmai_nexus_private;
	void		*dmai_iopte;
	uint_t		*dmai_sbi;
	void		*dmai_minfo;	/* random mapping information */
	dev_info_t	*dmai_rdip;	/* original requester's dev_info_t */
	ddi_dma_obj_t	dmai_object;	/* requester's object */
	ddi_dma_attr_t	dmai_attr;	/* DMA attributes */
	ddi_dma_cookie_t *dmai_cookie;	/* pointer to first DMA cookie */

	int		(*dmai_fault_check)(struct ddi_dma_impl *handle);
	void		(*dmai_fault_notify)(struct ddi_dma_impl *handle);
	int		dmai_fault;
	ndi_err_t	dmai_error;

} ddi_dma_impl_t;

#elif defined(__x86)

/*
 * ddi_dma_impl portion that genunix (sunddi.c) depends on. x86 rootnex
 * implementation specific state is in dmai_private.
 */
typedef struct ddi_dma_impl {
	ddi_dma_cookie_t *dmai_cookie; /* array of DMA cookies */
	uint_t		dmai_ncookies;
	uint_t		dmai_curcookie;
	void		*dmai_private;

	/*
	 * Information gathered from the original dma mapping
	 * request and saved for the lifetime of the mapping.
	 */
	uint_t		dmai_minxfer;
	uint_t		dmai_burstsizes;
	uint_t		dmai_rflags;	/* requester's flags + ours */
	int		dmai_nwin;
	dev_info_t	*dmai_rdip;	/* original requester's dev_info_t */

	ddi_dma_attr_t	dmai_attr;	/* DMA attributes */

	int		(*dmai_fault_check)(struct ddi_dma_impl *handle);
	void		(*dmai_fault_notify)(struct ddi_dma_impl *handle);
	int		dmai_fault;
	ndi_err_t	dmai_error;
} ddi_dma_impl_t;

#else
#error "struct ddi_dma_impl not defined for this architecture"
#endif  /* defined(__sparc) */

/*
 * For now DMA segments share state with the DMA handle
 */
typedef ddi_dma_impl_t ddi_dma_seg_impl_t;

/*
 * These flags use reserved bits from the dma request flags.
 *
 * A note about the DMP_NOSYNC flags: the root nexus will
 * set these as it sees best. If an intermediate nexus
 * actually needs these operations, then during the unwind
 * from the call to ddi_dma_bind, the nexus driver *must*
 * clear the appropriate flag(s). This is because, as an
 * optimization, ddi_dma_sync(9F) looks at these flags before
 * deciding to spend the time going back up the tree.
 */

#define	_DMCM1	DDI_DMA_RDWR|DDI_DMA_REDZONE|DDI_DMA_PARTIAL
#define	_DMCM2	DDI_DMA_CONSISTENT|DMP_VMEREQ
#define	DMP_DDIFLAGS	(_DMCM1|_DMCM2)
#define	DMP_SHADOW	0x20
#define	DMP_LKIOPB	0x40
#define	DMP_LKSYSV	0x80
#define	DMP_IOCACHE	0x100
#define	DMP_USEHAT	0x200
#define	DMP_PHYSADDR	0x400
#define	DMP_INVALID	0x800
#define	DMP_NOLIMIT	0x1000
#define	DMP_VMEREQ	0x10000000
#define	DMP_BYPASSNEXUS	0x20000000
#define	DMP_NODEVSYNC	0x40000000
#define	DMP_NOCPUSYNC	0x80000000
#define	DMP_NOSYNC	(DMP_NODEVSYNC|DMP_NOCPUSYNC)

/*
 * In order to complete a device to device mapping that
 * has percolated as high as an IU nexus (gone that high
 * because the DMA request is a VADDR type), we define
 * structure to use with the DDI_CTLOPS_DMAPMAPC request
 * that re-traverses the request tree to finish the
 * DMA 'mapping' for a device.
 */
struct dma_phys_mapc {
	struct ddi_dma_req *dma_req;	/* original request */
	ddi_dma_impl_t *mp;		/* current handle, or none */
	int nptes;			/* number of ptes */
	void *ptes;			/* ptes already read */
};

#define	MAXCALLBACK		20

/*
 * Callback definitions
 */
struct ddi_callback {
	struct ddi_callback	*c_nfree;
	struct ddi_callback	*c_nlist;
	int			(*c_call)();
	int			c_count;
	caddr_t			c_arg;
	size_t			c_size;
};

/*
 * Pure dynamic property declaration. A pure dynamic property is a property
 * for which a driver's prop_op(9E) implementation will return a value on
 * demand, but the property name does not exist on a property list (global,
 * driver, system, or hardware) - the person asking for the value must know
 * the name and type information.
 *
 * For a pure dynamic property to show up in a di_init() devinfo shapshot, the
 * devinfo driver must know name and type. The i_ddi_prop_dyn_t mechanism
 * allows a driver to define an array of the name/type information of its
 * dynamic properties. When a driver declares its dynamic properties in a
 * i_ddi_prop_dyn_t array, and registers that array using
 * i_ddi_prop_dyn_driver_set() the devinfo driver has sufficient information
 * to represent the properties in a snapshot - calling the driver's
 * prop_op(9E) to obtain values.
 *
 * The last element of a i_ddi_prop_dyn_t is detected via a NULL dp_name value.
 *
 * A pure dynamic property name associated with a minor_node/dev_t should be
 * defined with a dp_spec_type of S_IFCHR or S_IFBLK, as appropriate.  The
 * driver's prop_op(9E) entry point will be called for all
 * ddi_create_minor_node(9F) nodes of the specified spec_type. For a driver
 * where not all minor_node/dev_t combinations support the same named
 * properties, it is the responsibility of the prop_op(9E) implementation to
 * sort out what combinations are appropriate.
 *
 * A pure dynamic property of a devinfo node should be defined with a
 * dp_spec_type of 0.
 *
 * NB: Public DDI property interfaces no longer support pure dynamic
 * properties, but they are still still used.  A prime example is the cmlb
 * implementation of size(9P) properties. Using pure dynamic properties
 * reduces the space required to maintain per-partition information. Since
 * there are no public interfaces to create pure dynamic properties,
 * the i_ddi_prop_dyn_t mechanism should remain private.
 */
typedef struct i_ddi_prop_dyn {
	char	*dp_name;		/* name of dynamic property */
	int	dp_type;		/* DDI_PROP_TYPE_ of property */
	int	dp_spec_type;		/* 0, S_IFCHR, S_IFBLK */
} i_ddi_prop_dyn_t;
void			i_ddi_prop_dyn_driver_set(dev_info_t *,
			    i_ddi_prop_dyn_t *);
i_ddi_prop_dyn_t	*i_ddi_prop_dyn_driver_get(dev_info_t *);
void			i_ddi_prop_dyn_parent_set(dev_info_t *,
			    i_ddi_prop_dyn_t *);
i_ddi_prop_dyn_t	*i_ddi_prop_dyn_parent_get(dev_info_t *);
void			i_ddi_prop_dyn_cache_invalidate(dev_info_t *,
			    i_ddi_prop_dyn_t *);

/*
 * Device id - Internal definition.
 */
#define	DEVID_MAGIC_MSB		0x69
#define	DEVID_MAGIC_LSB		0x64
#define	DEVID_REV_MSB		0x00
#define	DEVID_REV_LSB		0x01
#define	DEVID_HINT_SIZE		4

typedef struct impl_devid {
	uchar_t	did_magic_hi;			/* device id magic # (msb) */
	uchar_t	did_magic_lo;			/* device id magic # (lsb) */
	uchar_t	did_rev_hi;			/* device id revision # (msb) */
	uchar_t	did_rev_lo;			/* device id revision # (lsb) */
	uchar_t	did_type_hi;			/* device id type (msb) */
	uchar_t	did_type_lo;			/* device id type (lsb) */
	uchar_t	did_len_hi;			/* length of devid data (msb) */
	uchar_t	did_len_lo;			/* length of devid data (lsb) */
	char	did_driver[DEVID_HINT_SIZE];	/* driver name - HINT */
	char	did_id[1];			/* start of device id data */
} impl_devid_t;

#define	DEVID_GETTYPE(devid)		((ushort_t) \
					    (((devid)->did_type_hi << NBBY) + \
					    (devid)->did_type_lo))

#define	DEVID_FORMTYPE(devid, type)	(devid)->did_type_hi = hibyte((type)); \
					(devid)->did_type_lo = lobyte((type));

#define	DEVID_GETLEN(devid)		((ushort_t) \
					    (((devid)->did_len_hi << NBBY) + \
					    (devid)->did_len_lo))

#define	DEVID_FORMLEN(devid, len)	(devid)->did_len_hi = hibyte((len)); \
					(devid)->did_len_lo = lobyte((len));

/*
 * Per PSARC/1995/352, a binary devid contains fields for <magic number>,
 * <revision>, <driver_hint>, <type>, <id_length>, and the <id> itself.
 * This proposal would encode the binary devid into a string consisting
 * of "<magic><revision>,<driver_hint>@<type><id>" as indicated below
 * (<id_length> is rederived from the length of the string
 * representation of the <id>):
 *
 *	<magic>		->"id"
 *
 *	<rev>		->"%d"	// "0" -> type of DEVID_NONE  "id0"
 *				// NOTE: PSARC/1995/352 <revision> is "1".
 *				// NOTE: support limited to 10 revisions
 *				//	in current implementation
 *
 *	<driver_hint>	->"%s"	// "sd"/"ssd"
 *				// NOTE: driver names limited to 4
 *				//	characters for <revision> "1"
 *
 *	<type>		->'w' |	// DEVID_SCSI3_WWN	<hex_id>
 *			'W' |	// DEVID_SCSI3_WWN	<ascii_id>
 *			't' |	// DEVID_SCSI3_VPD_T10	<hex_id>
 *			'T' |	// DEVID_SCSI3_VPD_T10	<ascii_id>
 *			'x' |	// DEVID_SCSI3_VPD_EUI	<hex_id>
 *			'X' |	// DEVID_SCSI3_VPD_EUI	<ascii_id>
 *			'n' |	// DEVID_SCSI3_VPD_NAA	<hex_id>
 *			'N' |	// DEVID_SCSI3_VPD_NAA	<ascii_id>
 *			's' |	// DEVID_SCSI_SERIAL	<hex_id>
 *			'S' |	// DEVID_SCSI_SERIAL	<ascii_id>
 *			'f' |	// DEVID_FAB		<hex_id>
 *			'F' |	// DEVID_FAB		<ascii_id>
 *			'e' |	// DEVID_ENCAP		<hex_id>
 *			'E' |	// DEVID_ENCAP		<ascii_id>
 *			'a' |	// DEVID_ATA_SERIAL	<hex_id>
 *			'A' |	// DEVID_ATA_SERIAL	<ascii_id>
 *			'd' |	// DEVID_NVME_NSID	<hex_id>
 *			'D' |	// DEVID_NVME_NSID	<ascii_id>
 *			'i' |	// DEVID_NVME_EUI64	<hex_id>
 *			'I' |	// DEVID_NVME_EUI64	<ascii_id>
 *			'g' |	// DEVID_NVME_NGUID	<hex_id>
 *			'G' |	// DEVID_NVME_NGUID	<ascii_id>
 *			'u' |	// unknown		<hex_id>
 *			'U'	// unknown		<ascii_id>
 *				// NOTE:lower case -> <hex_id>
 *				//	upper case -> <ascii_id>
 *				// NOTE:this covers all types currently
 *				//	defined for <revision> 1.
 *				// NOTE:a <type> can be added
 *				//	without changing the <revision>.
 *
 *	<id>		-> <ascii_id> |	// <type> is upper case
 *			<hex_id>	// <type> is lower case
 *
 *	<ascii_id>	// only if all bytes of binary <id> field
 *			// are in the set:
 *			//	[A-Z][a-z][0-9]+-.= and space and 0x00
 *			// the encoded form is:
 *			//	[A-Z][a-z][0-9]+-.= and _ and ~
 *			//	NOTE: ' ' <=> '_', 0x00 <=> '~'
 *			// these sets are chosen to avoid shell
 *			// and conflicts with DDI node names.
 *
 *	<hex_id>	// if not <ascii_id>; each byte of binary
 *			// <id> maps a to 2 digit ascii hex
 *			// representation in the string.
 *
 * This encoding provides a meaningful correlation between the /devices
 * path and the devid string where possible.
 *
 *   Fibre:
 *	sbus@6,0/SUNW,socal@d,10000/sf@1,0/ssd@w21000020370bb488,0:c,raw
 *	id1,ssd@w20000020370bb488:c,raw
 *
 *   Copper:
 *	sbus@7,0/SUNW,fas@3,8800000/sd@a,0:c
 *	id1,sd@SIBM_____1XY210__________:c
 */
/* determine if a byte of an id meets ASCII representation requirements */
#define	DEVID_IDBYTE_ISASCII(b)		(				\
	(((b) >= 'a') && ((b) <= 'z')) ||				\
	(((b) >= 'A') && ((b) <= 'Z')) ||				\
	(((b) >= '0') && ((b) <= '9')) ||				\
	(b == '+') || (b == '-') || (b == '.') || (b == '=') ||		\
	(b == ' ') || (b == 0x00))

/* set type to lower case to indicate that the did_id field is ascii */
#define	DEVID_TYPE_SETASCII(c)	(c - 0x20)	/* 'a' -> 'A' */

/* determine from type if did_id field is binary or ascii */
#define	DEVID_TYPE_ISASCII(c)	(((c) >= 'A') && ((c) <= 'Z'))

/* convert type field from binary to ascii */
#define	DEVID_TYPE_BINTOASCII(b)	(				\
	((b) == DEVID_SCSI3_WWN)	? 'w' :				\
	((b) == DEVID_SCSI3_VPD_T10)	? 't' :				\
	((b) == DEVID_SCSI3_VPD_EUI)	? 'x' :				\
	((b) == DEVID_SCSI3_VPD_NAA)	? 'n' :				\
	((b) == DEVID_SCSI_SERIAL)	? 's' :				\
	((b) == DEVID_FAB)		? 'f' :				\
	((b) == DEVID_ENCAP)		? 'e' :				\
	((b) == DEVID_ATA_SERIAL)	? 'a' :				\
	((b) == DEVID_NVME_NSID)	? 'd' :				\
	((b) == DEVID_NVME_EUI64)	? 'i' :				\
	((b) == DEVID_NVME_NGUID)	? 'g' :				\
	'u')						/* unknown */

/* convert type field from ascii to binary */
#define	DEVID_TYPE_ASCIITOBIN(c)	(				\
	(((c) == 'w') || ((c) == 'W'))	? DEVID_SCSI3_WWN :		\
	(((c) == 't') || ((c) == 'T'))	? DEVID_SCSI3_VPD_T10 :		\
	(((c) == 'x') || ((c) == 'X'))	? DEVID_SCSI3_VPD_EUI :		\
	(((c) == 'n') || ((c) == 'N'))	? DEVID_SCSI3_VPD_NAA :		\
	(((c) == 's') || ((c) == 'S'))	? DEVID_SCSI_SERIAL :		\
	(((c) == 'f') || ((c) == 'F'))	? DEVID_FAB :			\
	(((c) == 'e') || ((c) == 'E'))	? DEVID_ENCAP :			\
	(((c) == 'a') || ((c) == 'A'))	? DEVID_ATA_SERIAL :		\
	(((c) == 'd') || ((c) == 'D'))	? DEVID_NVME_NSID :		\
	(((c) == 'i') || ((c) == 'I'))	? DEVID_NVME_EUI64 :		\
	(((c) == 'g') || ((c) == 'G'))	? DEVID_NVME_NGUID :		\
	DEVID_MAXTYPE +1)				/* unknown */

/* determine if the type should be forced to hex encoding (non-ascii) */
#define	DEVID_TYPE_BIN_FORCEHEX(b) (	\
	((b) == DEVID_SCSI3_WWN) ||	\
	((b) == DEVID_SCSI3_VPD_EUI) ||	\
	((b) == DEVID_SCSI3_VPD_NAA) ||	\
	((b) == DEVID_NVME_EUI64) ||	\
	((b) == DEVID_NVME_NGUID) ||	\
	((b) == DEVID_FAB))

/* determine if the type is from a scsi3 vpd */
#define	IS_DEVID_SCSI3_VPD_TYPE(b) (	\
	((b) == DEVID_SCSI3_VPD_T10) ||	\
	((b) == DEVID_SCSI3_VPD_EUI) ||	\
	((b) == DEVID_SCSI3_VPD_NAA))

/* convert rev field from binary to ascii (only supports 10 revs) */
#define	DEVID_REV_BINTOASCII(b) (b + '0')

/* convert rev field from ascii to binary (only supports 10 revs) */
#define	DEVID_REV_ASCIITOBIN(c) (c - '0')

/* name of devid property */
#define	DEVID_PROP_NAME	"devid"

/*
 * prop_name used by pci_{save,restore}_config_regs()
 */
#define	SAVED_CONFIG_REGS "pci-config-regs"
#define	SAVED_CONFIG_REGS_MASK "pcie-config-regs-mask"
#define	SAVED_CONFIG_REGS_CAPINFO "pci-cap-info"

typedef struct pci_config_header_state {
	uint16_t	chs_command;
	uint8_t		chs_cache_line_size;
	uint8_t		chs_latency_timer;
	uint8_t		chs_header_type;
	uint8_t		chs_sec_latency_timer;
	uint8_t		chs_bridge_control;
	uint32_t	chs_base0;
	uint32_t	chs_base1;
	uint32_t	chs_base2;
	uint32_t	chs_base3;
	uint32_t	chs_base4;
	uint32_t	chs_base5;
} pci_config_header_state_t;

#ifdef _KERNEL

typedef struct pci_cap_save_desc {
	uint16_t	cap_offset;
	uint16_t	cap_id;
	uint32_t	cap_nregs;
} pci_cap_save_desc_t;

typedef struct pci_cap_entry {
	uint16_t		cap_id;
	uint16_t		cap_reg;
	uint16_t		cap_mask;
	uint32_t		cap_ndwords;
	uint32_t (*cap_save_func)(ddi_acc_handle_t confhdl, uint16_t cap_ptr,
	    uint32_t *regbuf, uint32_t ndwords);
} pci_cap_entry_t;

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_DDI_IMPLDEFS_H */