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