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