|
root / base / usr / src / uts / common / sys / sbp2
sbp2 Plain Text 997 lines 31.9 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
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SBP2_BUS_H
#define	_SYS_SBP2_BUS_H

/*
 * Serial Bus Protocol 2 (SBP-2) bus interface
 */

#include <sys/sbp2/common.h>
#include <sys/note.h>

#ifdef	__cplusplus
extern "C" {
#endif

enum {
	SBP2_BUS_REV_1	= 1,
	SBP2_BUS_REV	= SBP2_BUS_REV_1
};

typedef struct sbp2_bus_buf {
	struct sbp2_bus_buf *bb_next;	/* next in free list */
	void		*bb_hdl;	/* buffer handle */
	void		*bb_sbp2_priv;	/* SBP2 private data */
	size_t		bb_len;		/* buffer length */
	int		bb_flags;	/* flags */
	int		bb_dma_flags;	/* DDI_DMA_* flags */
	caddr_t		bb_kaddr;	/* kernel virtual address */
	uint64_t	bb_paddr;	/* physical address */
	uint64_t	bb_baddr;	/* bus address */
	void		(*bb_rq_cb)(struct sbp2_bus_buf *bb, void *reqh,
			    uint32_t *q);	/* quadlet read callback */
	void		(*bb_rb_cb)(struct sbp2_bus_buf *bb, void *reqh,
			    mblk_t **bpp, size_t len); /* block read callback */
	void		(*bb_wq_cb)(struct sbp2_bus_buf *bb, void *reqh,
			    uint32_t q);	/* quadlet write callback */
	void		(*bb_wb_cb)(struct sbp2_bus_buf *bb, void *reqh,
			    mblk_t **bpp);	/* block write callback */
} sbp2_bus_buf_t;

_NOTE(SCHEME_PROTECTS_DATA("unique per call", sbp2_bus_buf))

/* buffer flags */
enum {
	SBP2_BUS_BUF_DMA	= 0x01,	/* DMA buffer */
	SBP2_BUS_BUF_RD		= 0x02,	/* read buffer */
	SBP2_BUS_BUF_WR		= 0x04,	/* write buffer */
	SBP2_BUS_BUF_POSTED	= 0x08,	/* posted buffer */
	SBP2_BUS_BUF_RW		= (SBP2_BUS_BUF_RD | SBP2_BUS_BUF_WR),
	SBP2_BUS_BUF_WR_POSTED	= (SBP2_BUS_BUF_WR | SBP2_BUS_BUF_POSTED)
};

/* buffer request error codes */
enum {
	SBP2_BUS_BUF_SUCCESS		= 0,
	SBP2_BUS_BUF_FAILURE		= -1,	/* unspecified error */
	SBP2_BUS_BUF_ELENGTH		= 1,	/* wrong data length */
	SBP2_BUS_BUF_EBUSY		= 2	/* device busy */
};

typedef struct sbp2_bus {
	int		sb_rev;

	/* static parameters */
	uint64_t	sb_csr_base;	/* CSR base address */
	uint64_t	sb_cfgrom_addr;	/* Config ROM address */

	/* functions */
	ddi_iblock_cookie_t (*sb_get_iblock_cookie)(void *hdl);
	uint_t		(*sb_get_node_id)(void *hdl);
	int		(*sb_alloc_buf)(void *hdl, sbp2_bus_buf_t *buf);
	void		(*sb_free_buf)(void *hdl, sbp2_bus_buf_t *buf);
	int		(*sb_sync_buf)(void *hdl, sbp2_bus_buf_t *buf,
			    off_t offset, size_t length, int type);
	void		(*sb_buf_rd_done)(void *hdl, sbp2_bus_buf_t *buf,
			    void *reqh, int error);
	void		(*sb_buf_wr_done)(void *hdl, sbp2_bus_buf_t *buf,
			    void *reqh, int error);

	int		(*sb_alloc_cmd)(void *hdl, void **cmdp, int flags);
	void		(*sb_free_cmd)(void *hdl, void *cmd);
	int		(*sb_rq)(void *hdl, void *cmd, uint64_t addr,
			    uint32_t *q, int *berr);
	int		(*sb_rb)(void *hdl, void *cmd, uint64_t addr,
			    mblk_t **bpp, int len, int *err);
	int		(*sb_wq)(void *hdl, void *cmd, uint64_t addr,
			    uint32_t q, int *berr);
	int		(*sb_wb)(void *hdl, void *cmd, uint64_t addr,
			    mblk_t *bp, int len, int *berr);
} sbp2_bus_t;

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SBP2_BUS_H */
/*
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SBP2_COMMON_H
#define	_SYS_SBP2_COMMON_H

/*
 * Serial Bus Protocol 2 (SBP-2) common definitions
 */

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _LITTLE_ENDIAN
#define	SBP2_SWAP16(data)	\
	((((data) & 0xff) << 8) | ((data) >> 8))

#define	SBP2_SWAP32(data)	\
	(((uint32_t)SBP2_SWAP16((uint16_t)((data) & 0xffff)) << 16) | \
	(uint32_t)SBP2_SWAP16((uint16_t)((data) >> 16)))

#define	SBP2_SWAP16_1(data)	(data) = SBP2_SWAP16(data)
#define	SBP2_SWAP32_1(data)	(data) = SBP2_SWAP32(data)

#define	SBP2_SWAP16_2(data)	\
	((uint16_t *)(data))[0] = SBP2_SWAP16(((uint16_t *)(data))[0]);	\
	((uint16_t *)(data))[1] = SBP2_SWAP16(((uint16_t *)(data))[1]);

#define	SBP2_SWAP32_2(data)	\
	((uint32_t *)(data))[0] = SBP2_SWAP32(((uint32_t *)(data))[0]);	\
	((uint32_t *)(data))[1] = SBP2_SWAP32(((uint32_t *)(data))[1]);

#define	SBP2_SWAP32_BUF(data, len)	sbp2_swap32_buf((uint32_t *)data, len)

#else
#define	SBP2_SWAP16(data)	(data)
#define	SBP2_SWAP32(data)	(data)
#define	SBP2_SWAP16_1(data)
#define	SBP2_SWAP32_1(data)
#define	SBP2_SWAP16_2(data)
#define	SBP2_SWAP32_2(data)
#define	SBP2_SWAP32_BUF(data, len)
#endif

/*
 * serial bus address: it is a 64-bit value, but ORB structures require quadlet
 * (32-bit) alignment, so it is defined as two quadlets rather than one octlet
 */
typedef uint32_t sbp2_addr_t[2];

#define	SBP2_ADDR_NODE_ID		0xFFFF000000000000ULL
#define	SBP2_ADDR_NODE_ID_SHIFT		48
#define	SBP2_ADDR_OFFSET		0x0000FFFFFFFFFFFCULL

#define	SBP2_OFFSET_HI(offset)		(((offset) & SBP2_ADDR_OFFSET) >> 32)
#define	SBP2_OFFSET_LO(offset)		(((offset) & SBP2_ADDR_OFFSET))

#define	SBP2_ADDR_SET(var, addr, node_ID) { \
		((uint32_t *)(var))[0] = SBP2_SWAP32(((addr) | \
		((uint64_t)(node_ID) << SBP2_ADDR_NODE_ID_SHIFT)) >> 32); \
		((uint32_t *)(var))[1] = SBP2_SWAP32(SBP2_OFFSET_LO(addr)); \
	}

#define	SBP2_ADDR2UINT64(addr)	((((uint64_t)(addr)[0])) << 32) | ((addr)[1])

/* ORB pointer: serial bus address without node ID */
typedef uint32_t sbp2_orbp_t[2];

#define	SBP2_ORBP_NULL			0x8000000000000000ULL
#define	SBP2_ORBP_OFFSET		0x0000FFFFFFFFFFFCULL
#define	SBP2_ORBP_MASK			(SBP2_ORBP_NULL | SBP2_ORBP_OFFSET)

#define	SBP2_ORBP_HI(orbp)		\
		((uint32_t)(((orbp) & SBP2_ORBP_MASK) >> 32))
#define	SBP2_ORBP_LO(orbp)		((uint32_t)((orbp) & SBP2_ORBP_MASK))

#define	SBP2_ORBP_SET(var, orbp) { \
		((uint32_t *)(var))[0] = SBP2_SWAP32(SBP2_ORBP_HI(orbp)); \
		((uint32_t *)(var))[1] = SBP2_SWAP32(SBP2_ORBP_LO(orbp)); \
	}

#define	SBP2_ORBP2UINT64(orbp) \
	((((uint64_t)(orbp)[0] << 32) | (orbp)[1]) & SBP2_ORBP_OFFSET)


/*
 * return codes
 * NOTE: SBP2_SUCCESS/FAILURE values should be the same as DDI_SUCCESS/FAILURE
 */
enum {
	SBP2_SUCCESS		= 0,
	SBP2_FAILURE		= -1,	/* generic/undefined failure */
	SBP2_EINVAL		= 1,	/* invalid arguments */
	SBP2_ENOMEM		= 2,	/* memory not available */
	SBP2_EIO		= 3,	/* I/O operation failed */
	SBP2_EBUSY		= 4,	/* device busy */
	SBP2_EADDR		= 5,	/* wrong address */
	SBP2_EDEAD		= 6,	/* agent dead */
	SBP2_ETIMEOUT		= 7,	/* operation timed out */
	SBP2_ECFGROM		= 8,	/* bad/corrupted Config ROM */
	SBP2_EALREADY		= 9,	/* already exists/completed/etc */
	SBP2_ESTALE		= 10,	/* stale login session */
	SBP2_EDATA		= 11,	/* bad/corrupted data */
	SBP2_ENODEV		= 12,	/* device not there */
	SBP2_ECONTEXT		= 13	/* bad context for I/O operation */
};

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SBP2_COMMON_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SBP2_DEFS_H
#define	_SYS_SBP2_DEFS_H

/*
 * Serial Bus Protocol 2 (SBP-2) definitions
 *
 * References are to ANSI NCITS 325-1998 unless specified otherwise
 */

#include <sys/sbp2/common.h>
#include <sys/note.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Operation request blocks (ORB's)
 * Note that the targets specify the minimum ORB size (ref: 7.8.4)
 *
 * dummy ORB (ref: 5.1.1)
 */
typedef struct sbp2_dummy_orb {
	sbp2_orbp_t	do_next_orb;	/* next ORB pointer */
	uint32_t	do_ignored1[2];	/* ignored */
	uint16_t	do_params;	/* parameters */
	uint16_t	do_ignored2;	/* ignored */
} sbp2_dummy_orb_t;

/* parameters */
#define	SBP2_ORB_NOTIFY			0x8000	/* notify bit */
#define	SBP2_ORB_RQ_FMT			0x6000	/* ORB format */

/* ORB formats */
#define	SBP2_ORB_RQ_FMT_SBP2		0x0000	/* SBP2 ORB */
#define	SBP2_ORB_RQ_FMT_DUMMY		0x6000	/* dummy (NOP) ORB */

/* command block ORB (ref: 5.1.2) */
typedef struct sbp2_cmd_orb {
	sbp2_orbp_t	co_next_orb;	/* next ORB pointer */
	uint32_t	co_data_descr[2]; /* data descriptor */
	uint16_t	co_params;	/* parameters */
	uint16_t	co_data_size;	/* data size */
} sbp2_cmd_orb_t;

/* request */
#define	SBP2_ORB_CMD_DIR		0x0800
#define	SBP2_ORB_CMD_SPD		0x0700
#define	SBP2_ORB_CMD_SPD_SHIFT		8
#define	SBP2_ORB_CMD_MAX_PAYLOAD 	0x00F0
#define	SBP2_ORB_CMD_MAX_PAYLOAD_SHIFT 	4
#define	SBP2_ORB_CMD_PT			0x0008
#define	SBP2_ORB_CMD_PSZ		0x0007

/* speeds */
#define	SBP2_ORB_CMD_SPD_S100		0x0000
#define	SBP2_ORB_CMD_SPD_S200		0x0100
#define	SBP2_ORB_CMD_SPD_S400		0x0200
#define	SBP2_ORB_CMD_SPD_S800		0x0300
#define	SBP2_ORB_CMD_SPD_S1600		0x0400
#define	SBP2_ORB_CMD_SPD_S3200		0x0500

/* management ORB (ref: 5.1.3) */
typedef struct sbp2_mgt_orb {
	uint32_t	mo_fdep1[4];	/* function-dependent */
	uint16_t	mo_params;	/* parameters */
	uint16_t	mo_fdep2;	/* function-dependent */
	uint32_t	mo_fdep3;	/* function-dependent */
	sbp2_addr_t	mo_status_fifo;	/* status FIFO address */
} sbp2_mgt_orb_t;

/* parameters */
#define	SBP2_ORB_MGT_FUNC 		0x000F	/* mgt function */

/* mgt functions */
#define	SBP2_ORB_MGT_FUNC_LOGIN 	0x0000
#define	SBP2_ORB_MGT_FUNC_QUERY_LOGINS	0x0001
#define	SBP2_ORB_MGT_FUNC_RECONNECT 	0x0003
#define	SBP2_ORB_MGT_FUNC_SET_PASSWORD	0x0004
#define	SBP2_ORB_MGT_FUNC_LOGOUT 	0x0007
#define	SBP2_ORB_MGT_FUNC_ABORT_TASK 	0x000B
#define	SBP2_ORB_MGT_FUNC_ABORT_TASK_SET 0x000C
#define	SBP2_ORB_MGT_FUNC_LUN_RESET 	0x000E
#define	SBP2_ORB_MGT_FUNC_TARGET_RESET	0x000F

/* login ORB (ref: 5.1.3.1) */
typedef struct sbp2_login_orb {
	sbp2_addr_t	lo_passwd;	/* password */
	sbp2_addr_t	lo_resp;	/* response */
	uint16_t	lo_params;	/* parameters */
	uint16_t	lo_lun;		/* lun */
	uint16_t	lo_passwd_len;	/* password length */
	uint16_t	lo_resp_len;	/* response length */
	sbp2_addr_t	lo_status_fifo;	/* status FIFO address */
} sbp2_login_orb_t;

/* parameters */
#define	SBP2_ORB_LOGIN_EXCL		0x1000
#define	SBP2_ORB_LOGIN_RECONNECT	0x00F0
#define	SBP2_ORB_LOGIN_RECONNECT_SHIFT	4

/* login response */
typedef struct sbp2_login_resp {
	uint16_t	lr_len;		/* login length */
	uint16_t	lr_login_id;	/* login ID */
	sbp2_addr_t	lr_cmd_agent;	/* command block agent address */
	uint16_t	lr_reserved;	/* reserved */
	uint16_t	lr_reconnect_hold; /* reconnect hold */
} sbp2_login_resp_t;

/* query logins ORB (ref: 5.1.3.2) */
typedef struct sbp2_qlogins_orb {
	uint32_t	qo_reserved1[2]; /* reserved */
	sbp2_addr_t	qo_resp;	/* query response address */
	uint16_t	qo_params;	/* parameters */
	uint16_t	qo_lun;		/* LUN */
	uint16_t	qo_reserved2;	/* reserved */
	uint16_t	qo_len;		/* lengths */
	sbp2_addr_t	qo_status_fifo; /* status FIFO address */
} sbp2_qlogins_orb_t;

/* reconnect ORB (ref: 5.1.3.3) */
typedef struct sbp2_reconnect_orb {
	uint32_t	ro_reserved1[4]; /* reserved */
	uint16_t	ro_params;	/* parameters */
	uint16_t	ro_login_id;	/* login ID */
	uint32_t	ro_reserved2;	/* reserved */
	sbp2_addr_t	ro_status_fifo; /* status FIFO address */
} sbp2_reconnect_orb_t;

/* logout ORB (ref: 5.1.3.4) */
typedef struct sbp2_logout_orb {
	uint32_t	lo_reserved1[4]; /* reserved */
	uint16_t	lo_params;	/* parameters */
	uint16_t	lo_login_id;	/* login ID */
	uint32_t	lo_reserved2;	/* reserved */
	sbp2_addr_t	lo_status_fifo; /* status FIFO address */
} sbp2_logout_orb_t;

/* task management ORB (ref: 5.1.3.5) */
typedef struct sbp2_task_mgt_orb {
	sbp2_orbp_t	to_orb;		/* task pointer */
	uint32_t	to_reserved1[2]; /* reserved */
	uint16_t	to_params;	/* parameters */
	uint16_t	to_login_id;	/* login ID */
	uint32_t	to_reserved;	/* reserved */
	sbp2_addr_t	to_status_fifo; /* status FIFO address */
} sbp2_task_mgt_orb_t;

/* status block (ref: 5.3) */
typedef struct sbp2_status {
	uint8_t		st_param;	/* parameters */
	uint8_t		st_sbp_status;	/* SBP status */
	uint16_t	st_orb_offset_hi; /* ORB offset hi */
	uint32_t	st_orb_offset_lo; /* ORB offset lo */
	uint32_t	st_data[6];	/* command set-dependent data */
} sbp2_status_t;

/* parameters */
#define	SBP2_ST_SRC		0xC0
#define	SBP2_ST_SRC_SHIFT	6
#define	SBP2_ST_RESP		0x30
#define	SBP2_ST_RESP_SHIFT	4
#define	SBP2_ST_DEAD		0x08
#define	SBP2_ST_LEN		0x07

/* status origins */
#define	SBP2_ST_SRC_ORB		0x00
#define	SBP2_ST_SRC_ORB_NULL	0x40
#define	SBP2_ST_SRC_UNSOLICITED	0x80

/* response status */
#define	SBP2_ST_RESP_COMPLETE	0x00	/* REQUEST COMPLETE */
#define	SBP2_ST_RESP_TRANFAIL	0x10	/* TRANSPORT FAILURE */
#define	SBP2_ST_RESP_ILLREQ	0x20	/* ILLEGAL REQUEST */
#define	SBP2_ST_RESP_VENDOR	0x30	/* VENDOR DEPENDENT */

/* SBP status, when response status is REQUEST COMPLETE */
#define	SBP2_ST_SBP_NOINFO	0x00	/* no additional info */
#define	SBP2_ST_SBP_REQ_TYPE	0x01	/* req type not supported */
#define	SBP2_ST_SBP_SPD		0x02	/* speed not supported */
#define	SBP2_ST_SBP_PSZ		0x03	/* page size not supported */
#define	SBP2_ST_SBP_ACCESS	0x04	/* access denied */
#define	SBP2_ST_SBP_LUN		0x05	/* LUN not supported */
#define	SBP2_ST_SBP_PAYLOAD	0x06	/* max payload too small */
#define	SBP2_ST_SBP_RSRC	0x08	/* resources unavailable */
#define	SBP2_ST_SBP_FUNC	0x09	/* function rejected */
#define	SBP2_ST_SBP_LOGIN_ID	0x0A	/* login ID not recognized */
#define	SBP2_ST_SBP_DUMMY_ORB	0x0B	/* dummy ORB completed */
#define	SBP2_ST_SBP_REQ_ABORT	0x0C	/* request aborted */
#define	SBP2_ST_SBP_UNSPEC	0xFF	/* unspecified error */

/* SBP status, when response status is TRANSPORT FAILURE */
#define	SBP2_ST_SBP_OBJ		0xC0	/* failed object */
#define	SBP2_ST_SBP_ERR		0x0F	/* serial bus error */

/* objects */
#define	SBP2_ST_SBP_OBJ_ORB	0x00	/* ORB */
#define	SBP2_ST_SBP_OBJ_DATA	0x40	/* data buffer */
#define	SBP2_ST_SBP_OBJ_PT	0x80	/* page table */
#define	SBP2_ST_SBP_OBJ_UNSPEC	0xC0	/* unable to specify */

/* serial bus errors */
#define	SBP2_ST_SBP_ERR_ACK		0x00	/* missing ackknowledge */
#define	SBP2_ST_SBP_ERR_TIMEOUT		0x02	/* time-out error */
#define	SBP2_ST_SBP_ERR_ACK_BUSY_X	0x04	/* ack_busy_X */
#define	SBP2_ST_SBP_ERR_ACK_BUSY_A	0x05	/* ack_busy_A */
#define	SBP2_ST_SBP_ERR_ACK_BUSY_B	0x06	/* ack_busy_B */
#define	SBP2_ST_SBP_ERR_TARDY		0x0B	/* tardy limit exceeded */
#define	SBP2_ST_SBP_ERR_CONFLICT	0x0C	/* conflict error */
#define	SBP2_ST_SBP_ERR_DATA		0x0D	/* data error */
#define	SBP2_ST_SBP_ERR_TYPE		0x0E	/* type error */
#define	SBP2_ST_SBP_ERR_ADDR		0x0F	/* address error */


/* command block agent registers (ref: 6.4) */
#define	SBP2_AGENT_STATE_OFFSET		0x00
#define	SBP2_AGENT_RESET_OFFSET		0x04
#define	SBP2_ORB_POINTER_OFFSET		0x08
#define	SBP2_DOORBELL_OFFSET		0x10
#define	SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET 0x14

/* agent states */
#define	SBP2_AGENT_STATE_RESET		0
#define	SBP2_AGENT_STATE_ACTIVE		1
#define	SBP2_AGENT_STATE_SUSPENDED	2
#define	SBP2_AGENT_STATE_DEAD		3

/* page table parameters */
#define	SBP2_PT_ENT_SIZE		8		/* table entry size */
#define	SBP2_PT_SEGSIZE_MAX		(65536 - 8)	/* max segment size */

/* page table element for unrestricted page table (ref: 5.2.1) */
typedef struct sbp2_pt_unrestricted {
	uint16_t	pt_seg_len;	/* segment length */
	uint16_t	pt_seg_base_hi;	/* segment base hi */
	uint32_t	pt_seg_base_lo;	/* segment base lo */
} sbp2_pt_unrestricted_t;

/*
 * Configuration ROM
 *
 * key types & values
 */
#define	SBP2_KT_MGT_AGENT		1
#define	SBP2_KV_MGT_AGENT		0x14
#define	SBP2_KT_LUN			0
#define	SBP2_KV_LUN			0x14
#define	SBP2_KT_UNCHAR			0
#define	SBP2_KV_UNCHAR			0x3A

/* Logical_Unit_Number */
#define	SBP2_LUN_TYPE			0x001F0000	/* device_type */
#define	SBP2_LUN_TYPE_SHIFT		16
#define	SBP2_LUN_NUM			0x0000FFFF	/* lun */

/* Unit_Characteristics */
#define	SBP2_UNCHAR_MOT			0x0000FF00	/* mgt_ORB_timeout */
#define	SBP2_UNCHAR_MOT_SHIFT		8
#define	SBP2_UNCHAR_ORB_SIZE		0x000000FF	/* ORB_size */


_NOTE(SCHEME_PROTECTS_DATA("unique per ORB", { sbp2_dummy_orb sbp2_cmd_orb
    sbp2_mgt_orb sbp2_login_orb sbp2_login_resp sbp2_qlogins_orb
    sbp2_reconnect_orb sbp2_logout_orb sbp2_task_mgt_orb sbp2_status
    sbp2_pt_unrestricted }))

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SBP2_DEFS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SBP2_DRIVER_H
#define	_SYS_SBP2_DRIVER_H

/*
 * Serial Bus Protocol 2 (SBP-2) driver interfaces
 */

#include <sys/sbp2/defs.h>
#include <sys/sbp2/bus.h>
#include <sys/sysmacros.h>
#include <sys/note.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Config ROM definitions
 *
 * bus info block
 */
typedef struct sbp2_cfgrom_bib {
	int			cb_len;		/* info_length */
	uint32_t		*cb_buf;	/* data buffer */
} sbp2_cfgrom_bib_t;

/* directory */
typedef struct sbp2_cfgrom_dir {
	struct sbp2_cfgrom_ent	*cd_ent;	/* array of entries */
	int			cd_cnt;		/* # of entries with data */
	int			cd_size;	/* # of allocated entries */
} sbp2_cfgrom_dir_t;

/* directory entry */
typedef struct sbp2_cfgrom_ent {
	uint8_t			ce_kt;		/* key type */
	uint8_t			ce_kv;		/* key value */
	uint16_t		ce_len;		/* length in quadlets */
	uint64_t		ce_offset;	/* entry's CSR offset */
	struct sbp2_cfgrom_ent	*ce_ref;	/* referred entry (text leaf) */
	union {					/* data depends on key type: */
		uint32_t	imm;		/* immediate value */
		uint32_t	offset;		/* CSR offset */
		uint32_t	*leaf;		/* leaf */
		sbp2_cfgrom_dir_t dir;		/* directory */
	} ce_data;
} sbp2_cfgrom_ent_t;

/* entire Config ROM */
typedef struct sbp2_cfgrom {
	sbp2_cfgrom_bib_t	cr_bib;		/* bus info block */
	sbp2_cfgrom_ent_t	cr_root;	/* root directory */
} sbp2_cfgrom_t;

_NOTE(SCHEME_PROTECTS_DATA("stable data", {
    sbp2_cfgrom_bib sbp2_cfgrom_dir sbp2_cfgrom_ent sbp2_cfgrom }))

/*
 * SBP-2 definitions
 */

/* task states */
typedef enum {
	SBP2_TASK_INIT,		/* initial state */
	SBP2_TASK_PEND,		/* put on the list, pending completion */
	SBP2_TASK_COMP,		/* task completed */
	SBP2_TASK_PROC		/* status being processed */
} sbp2_task_state_t;

/* task errors */
typedef enum {
	SBP2_TASK_ERR_NONE,	/* no error */
	SBP2_TASK_ERR_DEAD,	/* agent dead */
	SBP2_TASK_ERR_BUS,	/* bus error */
	SBP2_TASK_ERR_TIMEOUT,	/* timed out */
	SBP2_TASK_ERR_ABORT,	/* task aborted */
	SBP2_TASK_ERR_LUN_RESET, /* lun reset */
	SBP2_TASK_ERR_TGT_RESET	/* target reset */
} sbp2_task_error;

/*
 * task
 */
typedef struct sbp2_task {
	struct sbp2_task	*ts_next;	/* next task */
	struct sbp2_task	*ts_prev;	/* previous task */
	struct sbp2_ses		*ts_ses;	/* session we belong to */
	void			*ts_drv_priv;	/* driver private data */
	sbp2_bus_buf_t		*ts_buf;	/* bus buffer */
	int			ts_timeout;	/* task timeout in seconds */
	timeout_id_t		ts_timeout_id;	/* timeout ID */
	sbp2_task_state_t	ts_state;	/* task state */
	sbp2_task_error		ts_error;	/* error */
	int			ts_bus_error;	/* bus error */
	sbp2_status_t		ts_status;	/* status block */
	hrtime_t		ts_time_start;
	hrtime_t		ts_time_comp;
} sbp2_task_t;

_NOTE(SCHEME_PROTECTS_DATA("unique per call", sbp2_task))

/* fetch agent */
typedef struct sbp2_agent {
	struct sbp2_tgt		*a_tgt;		/* target we belong to */
	kmutex_t		a_mutex;	/* structure mutex */
	uint16_t		a_state;	/* current agent state */
	kcondvar_t		a_cv;		/* agent state cv */
	boolean_t		a_acquired;	/* acquired flag */

	/* commands */
	void			*a_cmd;		/* fetch agent cmd */
	mblk_t			*a_cmd_data;	/* cmd data */

	sbp2_task_t		*a_active_task;	/* active task */

	/* register offsets */
	uint64_t		a_reg_agent_state; /* AGENT_STATE */
	uint64_t		a_reg_agent_reset; /* AGENT_RESET */
	uint64_t		a_reg_orbp;	/* ORB_POINTER */
	uint64_t		a_reg_doorbell;	/* DOORBELL */
	uint64_t		a_reg_unsol_status_enable;
						/* UNSOLICITED_STATUS_ENABLE */
} sbp2_agent_t;

_NOTE(MUTEX_PROTECTS_DATA(sbp2_agent::a_mutex, sbp2_agent))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_agent::{
    a_tgt a_reg_agent_state a_reg_agent_reset a_reg_orbp a_reg_doorbell
    a_reg_unsol_status_enable }))
_NOTE(SCHEME_PROTECTS_DATA("a_acquired", sbp2_agent::{
    a_cmd a_cmd_data a_active_task }))

/* session is a period between login and logout */
typedef struct sbp2_ses {
	struct sbp2_tgt		*s_tgt;		/* target we belong to */
	struct sbp2_lun		*s_lun;		/* unit we belong to */
	kmutex_t		s_mutex;	/* structure mutex */
	struct sbp2_ses		*s_next;	/* next session */

	uint16_t		s_id;		/* login ID */
	uint64_t		s_agent_offset;	/* fetch agent offset */
	sbp2_agent_t		s_agent;	/* fetch agent */
	sbp2_bus_buf_t		s_status_fifo_buf; /* status FIFO */

	/* task list (command ORB's) */
	kmutex_t		s_task_mutex;		/* protects task list */
	sbp2_task_t		*s_task_head;		/* first on the list */
	sbp2_task_t		*s_task_tail;		/* last on the list */
	int			s_task_cnt;		/* # tasks */
	void			(*s_status_cb)(void *, sbp2_task_t *);
	void			*s_status_cb_arg;
} sbp2_ses_t;

_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_mutex, sbp2_ses))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_ses::{
    s_tgt s_lun s_id s_agent_offset s_agent s_status_fifo_buf s_status_cb
    s_status_cb_arg }))
_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_ses::{
    s_task_head s_task_tail s_task_cnt }))
_NOTE(MUTEX_PROTECTS_DATA(sbp2_ses::s_task_mutex, sbp2_task::{
    ts_next ts_prev }))

/* buffer list */
typedef struct sbp2_buf_list {
	kmutex_t		bl_mutex;
	int			bl_len;		/* number of elements */
	sbp2_bus_buf_t		*bl_head;	/* first element */
	sbp2_bus_buf_t		*bl_tail;	/* last element */
} sbp2_buf_list_t;

/* logical unit */
typedef struct sbp2_lun {
	struct sbp2_tgt		*l_tgt;		/* target we belong to */
	uint16_t		l_lun;		/* logical unit number */
	uint8_t			l_type;		/* device type */
	sbp2_ses_t		*l_ses;		/* login sessions */
	sbp2_buf_list_t		l_orb_freelist;	/* ORB freelist */


	sbp2_login_resp_t	l_login_resp;	/* login response */
	boolean_t		l_logged_in;	/* true if logged in */
	boolean_t		l_reconnecting;	/* true if being reconnected */
} sbp2_lun_t;

enum {
	SBP2_ORB_FREELIST_MAX	= 3	/* max # of elements on freelist */
};

/* per-target statistics */
typedef struct sbp2_tgt_stat {
	hrtime_t		stat_cfgrom_last_parse_time;
	uint_t			stat_submit_orbp;
	uint_t			stat_submit_doorbell;
	uint_t			stat_status_dead;
	uint_t			stat_status_short;
	uint_t			stat_status_unsolicited;
	uint_t			stat_status_notask;
	uint_t			stat_status_mgt_notask;
	uint_t			stat_agent_worbp;
	uint_t			stat_agent_worbp_fail;
	uint_t			stat_agent_wreset;
	uint_t			stat_agent_wreset_fail;
	uint_t			stat_task_max;
} sbp2_tgt_stat_t;

/* target */
typedef struct sbp2_tgt {
	struct sbp2_bus		*t_bus;			/* bus */
	void			*t_bus_hdl;		/* bus handle */
	kmutex_t		t_mutex;		/* structure mutex */
	sbp2_lun_t		*t_lun;			/* logical unit array */
	int			t_nluns;		/* # logical units */
	int			t_nluns_alloc;		/* # luns allocated */

	/* congif ROM */
	sbp2_cfgrom_t		t_cfgrom;		/* parsed cfgrom */
	hrtime_t		t_last_cfgrd;		/* cfgrom timestamp */
	int			t_orb_size;		/* ORB_size */

	/* management agent */
	uint64_t		t_mgt_agent;		/* mgt agent address */
	int			t_mot;			/* mgt timeout, ms */
	boolean_t		t_mgt_agent_acquired;	/* acquired flag */
	kcondvar_t		t_mgt_agent_cv;		/* cv for busy flag */
	sbp2_bus_buf_t		t_mgt_orb_buf;		/* mgt ORB */
	void			*t_mgt_cmd;		/* command */
	mblk_t			*t_mgt_cmd_data;	/* command data */
	sbp2_bus_buf_t		t_mgt_status_fifo_buf;	/* status FIFO buf */
	sbp2_status_t		t_mgt_status;		/* status block */
	boolean_t		t_mgt_status_rcvd;	/* status received? */
	kcondvar_t		t_mgt_status_cv;	/* status FIFO cv */
	sbp2_bus_buf_t		t_mgt_login_resp_buf;	/* login response */

	sbp2_tgt_stat_t		t_stat;			/* statistics */
} sbp2_tgt_t;

_NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_tgt))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_tgt::{
    t_bus t_bus_hdl t_lun t_nluns t_nluns_alloc t_cfgrom t_last_cfgrd
    t_orb_size t_mgt_agent t_mot }))
_NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_tgt::{
    t_mgt_orb_buf t_mgt_cmd t_mgt_cmd_data t_mgt_status_fifo_buf
    t_mgt_status_rcvd t_mgt_login_resp_buf }))
_NOTE(SCHEME_PROTECTS_DATA("statistics", sbp2_tgt::t_stat))

_NOTE(MUTEX_PROTECTS_DATA(sbp2_tgt::t_mutex, sbp2_lun))
_NOTE(SCHEME_PROTECTS_DATA("stable data", sbp2_lun::{
    l_tgt l_lun l_type l_ses }))
_NOTE(SCHEME_PROTECTS_DATA("t_mgt_agent_cv", sbp2_lun::l_login_resp))

_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_mutex))
_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_ses::s_task_mutex))
_NOTE(LOCK_ORDER(sbp2_tgt::t_mutex sbp2_agent::a_mutex))

#define	SBP2_ORB_SIZE_ROUNDUP(tp, size) roundup(size, (tp)->t_orb_size)

/* walker flags */
enum {
	SBP2_WALK_DIRONLY	= 0x01	/* walk directories only */
};

/* walker return codes */
enum {
	SBP2_WALK_CONTINUE,
	SBP2_WALK_STOP
};

int sbp2_tgt_init(void *, struct sbp2_bus *, int, sbp2_tgt_t **);
void sbp2_tgt_fini(sbp2_tgt_t *);
void sbp2_tgt_disconnect(sbp2_tgt_t *);
int sbp2_tgt_reconnect(sbp2_tgt_t *);
int sbp2_tgt_reset(sbp2_tgt_t *, int *);
int sbp2_tgt_get_cfgrom(sbp2_tgt_t *, sbp2_cfgrom_t **);
int sbp2_tgt_get_lun_cnt(sbp2_tgt_t *);
sbp2_lun_t *sbp2_tgt_get_lun(sbp2_tgt_t *, int);

int sbp2_lun_reset(sbp2_lun_t *, int *);
int sbp2_lun_login(sbp2_lun_t *, sbp2_ses_t **, void (*)(void *, sbp2_task_t *),
    void *, int *);
int sbp2_lun_logout(sbp2_lun_t *, sbp2_ses_t **, int *, boolean_t);

int sbp2_ses_reconnect(sbp2_ses_t *, int *, uint16_t);
int sbp2_ses_submit_task(sbp2_ses_t *, sbp2_task_t *);
void sbp2_ses_nudge(sbp2_ses_t *);
int sbp2_ses_remove_task(sbp2_ses_t *, sbp2_task_t *);
sbp2_task_t *sbp2_ses_find_task_state(sbp2_ses_t *, sbp2_task_state_t);
sbp2_task_t *sbp2_ses_remove_first_task(sbp2_ses_t *);
sbp2_task_t *sbp2_ses_remove_first_task_state(sbp2_ses_t *, sbp2_task_state_t);
sbp2_task_t *sbp2_ses_cancel_first_task(sbp2_ses_t *);
int sbp2_ses_agent_reset(sbp2_ses_t *, int *);
int sbp2_ses_abort_task(sbp2_ses_t *, sbp2_task_t *, int *);
int sbp2_ses_abort_task_set(sbp2_ses_t *, int *);

int sbp2_task_orb_alloc(sbp2_lun_t *, sbp2_task_t *, int);
void sbp2_task_orb_free(sbp2_lun_t *, sbp2_task_t *);
void *sbp2_task_orb_kaddr(sbp2_task_t *);
void sbp2_task_orb_sync(sbp2_lun_t *, sbp2_task_t *, int);

void sbp2_swap32_buf(uint32_t *, int);

void sbp2_cfgrom_walk(sbp2_cfgrom_ent_t *,
    int (*)(void *, sbp2_cfgrom_ent_t *, int), void *);
sbp2_cfgrom_ent_t *sbp2_cfgrom_ent_by_key(sbp2_cfgrom_ent_t *, int8_t, int8_t,
    int);


#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SBP2_DRIVER_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 2004 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SYS_SBP2_IMPL_H
#define	_SYS_SBP2_IMPL_H

/*
 * Serial Bus Protocol 2 (SBP-2) implementation
 */

#include <sys/sbp2/common.h>
#include <sys/sbp2/bus.h>
#include <sys/sbp2/driver.h>
#include <sys/note.h>

#ifdef	__cplusplus
extern "C" {
#endif

/* Config ROM parser internal structure */
typedef struct sbp2_cfgrom_parse_arg {
	sbp2_cfgrom_ent_t	*pa_dir;	/* directory to parse */
	sbp2_cfgrom_ent_t	*pa_pdir;	/* parent directory */
	sbp2_cfgrom_ent_t	*pa_ref;	/* referred entry */
	int			pa_depth;	/* current depth */
} sbp2_cfgrom_parse_arg_t;

typedef struct sbp2_cfgrom_ent_by_key {
	uint8_t			kt;
	uint8_t			kv;
	int			num;
	sbp2_cfgrom_ent_t	*ent;
	int			cnt;
} sbp2_cfgrom_ent_by_key_t;

_NOTE(SCHEME_PROTECTS_DATA("unique per call", { sbp2_cfgrom_ent_by_key
    sbp2_cfgrom_parse_arg }))

enum {
	SBP2_CFGROM_MAX_DEPTH	= 5,	/* max directory depth */
	SBP2_CFGROM_GROW_INCR	= 4,	/* entry array growth increment */

	SBP2_MOT_MIN		= 500,	/* minimum mgt ORB timeout, in ms */
	SBP2_MOT_DFLT		= 2000,	/* default mgt ORB timeout, in ms */
	SBP2_ORB_SIZE_MIN	= 4,	/* minimum ORB size, in bytes */
	SBP2_ORB_SIZE_DFLT	= 32	/* default ORB size, in bytes */
};

/* busops macros */
#define	SBP2_CSR_BASE(t)	t->t_bus->sb_csr_base
#define	SBP2_CFGROM_ADDR(t)	t->t_bus->sb_cfgrom_addr
#define	SBP2_GET_IBLOCK_COOKIE(t) \
	(t)->t_bus->sb_get_iblock_cookie((t)->t_bus_hdl)
#define	SBP2_GET_NODE_ID(t)	(t)->t_bus->sb_get_node_id((t)->t_bus_hdl)
#define	SBP2_ALLOC_BUF(t, buf)	(t)->t_bus->sb_alloc_buf((t)->t_bus_hdl, buf)
#define	SBP2_FREE_BUF(t, buf)	(t)->t_bus->sb_free_buf((t)->t_bus_hdl, buf)
#define	SBP2_SYNC_BUF(t, buf, offset, length, type) \
	(t)->t_bus->sb_sync_buf((t)->t_bus_hdl, buf, offset, length, type)
#define	SBP2_BUF_RD_DONE(t, buf, reqh, error) \
	(t)->t_bus->sb_buf_rd_done((t)->t_bus_hdl, buf, reqh, error)
#define	SBP2_BUF_WR_DONE(t, buf, reqh, error) \
	(t)->t_bus->sb_buf_wr_done((t)->t_bus_hdl, buf, reqh, error)
#define	SBP2_ALLOC_CMD(t, cmdp, f) \
	(t)->t_bus->sb_alloc_cmd((t)->t_bus_hdl, cmdp, f)
#define	SBP2_FREE_CMD(t, cmd) \
	(t)->t_bus->sb_free_cmd((t)->t_bus_hdl, cmd)
#define	SBP2_RQ(t, cmd, addr, q, berr) \
	(t)->t_bus->sb_rq((t)->t_bus_hdl, cmd, addr, q, berr)
#define	SBP2_RB(t, cmd, addr, bp, len, berr) \
	(t)->t_bus->sb_rb((t)->t_bus_hdl, cmd, addr, bp, len, berr)
#define	SBP2_WQ(t, cmd, addr, q, berr) \
	(t)->t_bus->sb_wq((t)->t_bus_hdl, cmd, addr, q, berr)
#define	SBP2_WB(t, cmd, addr, bp, len, berr) \
	(t)->t_bus->sb_wb((t)->t_bus_hdl, cmd, addr, bp, len, berr)

int	sbp2_cfgrom_parse(sbp2_tgt_t *, sbp2_cfgrom_t *);
void	sbp2_cfgrom_free(sbp2_tgt_t *, sbp2_cfgrom_t *);

#ifdef	__cplusplus
}
#endif

#endif	/* _SYS_SBP2_IMPL_H */