xref: /illumos-gate/usr/src/uts/common/io/scsi/impl/scsi_capabilities.c (revision d3d50737e566cade9a08d73d2af95105ac7cd960)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  *
30  * Generic Capabilities Routines
31  *
32  */
33 
34 #include <sys/scsi/scsi.h>
35 #ifdef	__x86
36 #include <sys/ddi_isa.h>
37 #endif
38 
39 #define	A_TO_TRAN(ap)	(ap->a_hba_tran)
40 
41 
42 int
43 scsi_ifgetcap(struct scsi_address *ap, char *cap, int whom)
44 {
45 	int capability;
46 #ifdef	__x86
47 	ddi_dma_attr_t *dmaattr;
48 	int ckey;
49 #endif
50 
51 
52 	capability = (*A_TO_TRAN(ap)->tran_getcap)(ap, cap, whom);
53 
54 #ifdef	__x86
55 	if (cap != NULL) {
56 		ckey = scsi_hba_lookup_capstr(cap);
57 		dmaattr = &ap->a_hba_tran->tran_dma_attr;
58 		switch (ckey) {
59 		case SCSI_CAP_DMA_MAX:
60 			/*
61 			 * If the HBA is unable to reach all the memory in
62 			 * the system, the maximum copy buffer size may limit
63 			 * the size of the max DMA.
64 			 */
65 			if (i_ddi_copybuf_required(dmaattr)) {
66 				capability = MIN(capability,
67 				    i_ddi_copybuf_size());
68 			}
69 
70 			/*
71 			 * make sure the value we return is a whole multiple of
72 			 * the granlarity.
73 			 */
74 			if (dmaattr->dma_attr_granular > 1) {
75 				capability = capability -
76 				    (capability % dmaattr->dma_attr_granular);
77 			}
78 
79 			break;
80 
81 		case SCSI_CAP_DMA_MAX_ARCH:
82 			capability = i_ddi_dma_max(ap->a_hba_tran->tran_hba_dip,
83 			    dmaattr);
84 
85 			break;
86 
87 		/*FALLTHROUGH*/
88 		}
89 	}
90 #endif
91 
92 	return (capability);
93 }
94 
95 int
96 scsi_ifsetcap(struct scsi_address *ap, char *cap, int value, int whom)
97 {
98 	int rval;
99 	int cidx;
100 
101 	rval = (*A_TO_TRAN(ap)->tran_setcap)(ap, cap, value, whom);
102 	if (rval == 1) {
103 		cidx = scsi_hba_lookup_capstr(cap);
104 		if (cidx == SCSI_CAP_SECTOR_SIZE) {
105 			/*
106 			 * if we have successfully changed the
107 			 * granularity update SCSA's copy
108 			 */
109 			A_TO_TRAN(ap)->tran_dma_attr.dma_attr_granular =
110 			    value;
111 		}
112 	}
113 	return (rval);
114 }
115