17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
58faf39b2Staylor  * Common Development and Distribution License (the "License").
68faf39b2Staylor  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*1b94a41bSChris Horne  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * Generic Capabilities Routines
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <sys/scsi/scsi.h>
3236945f79Smrj #ifdef	__x86
3336945f79Smrj #include <sys/ddi_isa.h>
3436945f79Smrj #endif
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #define	A_TO_TRAN(ap)	(ap->a_hba_tran)
377c478bd9Sstevel@tonic-gate 
3836945f79Smrj 
397c478bd9Sstevel@tonic-gate int
scsi_ifgetcap(struct scsi_address * ap,char * cap,int whom)407c478bd9Sstevel@tonic-gate scsi_ifgetcap(struct scsi_address *ap, char *cap, int whom)
417c478bd9Sstevel@tonic-gate {
4236945f79Smrj 	int capability;
4336945f79Smrj #ifdef	__x86
4436945f79Smrj 	ddi_dma_attr_t *dmaattr;
4536945f79Smrj 	int ckey;
4636945f79Smrj #endif
4736945f79Smrj 
4836945f79Smrj 
4936945f79Smrj 	capability = (*A_TO_TRAN(ap)->tran_getcap)(ap, cap, whom);
5036945f79Smrj 
5136945f79Smrj #ifdef	__x86
5236945f79Smrj 	if (cap != NULL) {
5336945f79Smrj 		ckey = scsi_hba_lookup_capstr(cap);
5436945f79Smrj 		dmaattr = &ap->a_hba_tran->tran_dma_attr;
5536945f79Smrj 		switch (ckey) {
5636945f79Smrj 		case SCSI_CAP_DMA_MAX:
5736945f79Smrj 			/*
5836945f79Smrj 			 * If the HBA is unable to reach all the memory in
5936945f79Smrj 			 * the system, the maximum copy buffer size may limit
6036945f79Smrj 			 * the size of the max DMA.
6136945f79Smrj 			 */
6236945f79Smrj 			if (i_ddi_copybuf_required(dmaattr)) {
6336945f79Smrj 				capability = MIN(capability,
6436945f79Smrj 				    i_ddi_copybuf_size());
6536945f79Smrj 			}
6636945f79Smrj 
6736945f79Smrj 			/*
6836945f79Smrj 			 * make sure the value we return is a whole multiple of
6936945f79Smrj 			 * the granlarity.
7036945f79Smrj 			 */
7136945f79Smrj 			if (dmaattr->dma_attr_granular > 1) {
7236945f79Smrj 				capability = capability -
7336945f79Smrj 				    (capability % dmaattr->dma_attr_granular);
7436945f79Smrj 			}
7536945f79Smrj 
7636945f79Smrj 			break;
7736945f79Smrj 
7836945f79Smrj 		case SCSI_CAP_DMA_MAX_ARCH:
7936945f79Smrj 			capability = i_ddi_dma_max(ap->a_hba_tran->tran_hba_dip,
8036945f79Smrj 			    dmaattr);
8136945f79Smrj 
8236945f79Smrj 			break;
8336945f79Smrj 
8436945f79Smrj 		/*FALLTHROUGH*/
8536945f79Smrj 		}
8636945f79Smrj 	}
8736945f79Smrj #endif
8836945f79Smrj 
8936945f79Smrj 	return (capability);
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate int
scsi_ifsetcap(struct scsi_address * ap,char * cap,int value,int whom)937c478bd9Sstevel@tonic-gate scsi_ifsetcap(struct scsi_address *ap, char *cap, int value, int whom)
947c478bd9Sstevel@tonic-gate {
958faf39b2Staylor 	int rval;
968faf39b2Staylor 	int cidx;
978faf39b2Staylor 
988faf39b2Staylor 	rval = (*A_TO_TRAN(ap)->tran_setcap)(ap, cap, value, whom);
99*1b94a41bSChris Horne 	if ((rval == 1) || A_TO_TRAN(ap)->tran_setup_pkt) {
1008faf39b2Staylor 		cidx = scsi_hba_lookup_capstr(cap);
1018faf39b2Staylor 		if (cidx == SCSI_CAP_SECTOR_SIZE) {
1028faf39b2Staylor 			/*
1038faf39b2Staylor 			 * if we have successfully changed the
1048faf39b2Staylor 			 * granularity update SCSA's copy
1058faf39b2Staylor 			 */
1068faf39b2Staylor 			A_TO_TRAN(ap)->tran_dma_attr.dma_attr_granular =
10736945f79Smrj 			    value;
1088faf39b2Staylor 		}
1098faf39b2Staylor 	}
1108faf39b2Staylor 	return (rval);
1117c478bd9Sstevel@tonic-gate }
112