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 (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 *
27 * Generic Capabilities Routines
28 *
29 */
30
31 #include <sys/scsi/scsi.h>
32 #ifdef __x86
33 #include <sys/ddi_isa.h>
34 #endif
35
36 #define A_TO_TRAN(ap) (ap->a_hba_tran)
37
38
39 int
scsi_ifgetcap(struct scsi_address * ap,char * cap,int whom)40 scsi_ifgetcap(struct scsi_address *ap, char *cap, int whom)
41 {
42 int capability;
43 #ifdef __x86
44 ddi_dma_attr_t *dmaattr;
45 int ckey;
46 #endif
47
48
49 capability = (*A_TO_TRAN(ap)->tran_getcap)(ap, cap, whom);
50
51 #ifdef __x86
52 if (cap != NULL) {
53 ckey = scsi_hba_lookup_capstr(cap);
54 dmaattr = &ap->a_hba_tran->tran_dma_attr;
55 switch (ckey) {
56 case SCSI_CAP_DMA_MAX:
57 /*
58 * If the HBA is unable to reach all the memory in
59 * the system, the maximum copy buffer size may limit
60 * the size of the max DMA.
61 */
62 if (i_ddi_copybuf_required(dmaattr)) {
63 capability = MIN(capability,
64 i_ddi_copybuf_size());
65 }
66
67 /*
68 * make sure the value we return is a whole multiple of
69 * the granlarity.
70 */
71 if (dmaattr->dma_attr_granular > 1) {
72 capability = capability -
73 (capability % dmaattr->dma_attr_granular);
74 }
75
76 break;
77
78 case SCSI_CAP_DMA_MAX_ARCH:
79 capability = i_ddi_dma_max(ap->a_hba_tran->tran_hba_dip,
80 dmaattr);
81
82 break;
83
84 /*FALLTHROUGH*/
85 }
86 }
87 #endif
88
89 return (capability);
90 }
91
92 int
scsi_ifsetcap(struct scsi_address * ap,char * cap,int value,int whom)93 scsi_ifsetcap(struct scsi_address *ap, char *cap, int value, int whom)
94 {
95 int rval;
96 int cidx;
97
98 rval = (*A_TO_TRAN(ap)->tran_setcap)(ap, cap, value, whom);
99 if ((rval == 1) || A_TO_TRAN(ap)->tran_setup_pkt) {
100 cidx = scsi_hba_lookup_capstr(cap);
101 if (cidx == SCSI_CAP_SECTOR_SIZE) {
102 /*
103 * if we have successfully changed the
104 * granularity update SCSA's copy
105 */
106 A_TO_TRAN(ap)->tran_dma_attr.dma_attr_granular =
107 value;
108 }
109 }
110 return (rval);
111 }
112