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 */
|