1 /* 2 * Copyright (c) 2003-2005 by Siarzhuk Zharski <imker@gmx.li> 3 * Distributed under the terms of the BSD License. 4 * 5 */ 6 7 /** handling SCSI data-buffer (both usual "plain" and scatter/gather ones) */ 8 9 #include <string.h> 10 11 #include "usb_scsi.h" 12 13 #include <malloc.h> 14 #include "tracing.h" 15 #include "sg_buffer.h" 16 17 /** 18 \fn:init_sg_buffer 19 TODO!!! 20 */ 21 status_t 22 init_sg_buffer(sg_buffer *sgb, CCB_SCSIIO *ccbio) 23 { 24 status_t status = B_NO_INIT; 25 if(0 != sgb){ 26 memset(sgb, 0, sizeof(sg_buffer)); 27 /* setup scatter/gather if exists in CCBIO*/ 28 if(ccbio->cam_ch.cam_flags & CAM_SCATTER_VALID) { 29 sgb->piov = (iovec *) ccbio->cam_data_ptr; 30 sgb->count = ccbio->cam_sglist_cnt; 31 } else { 32 sgb->iov.iov_base = (iovec *) ccbio->cam_data_ptr; 33 sgb->iov.iov_len = ccbio->cam_dxfer_len; 34 sgb->piov = &sgb->iov; 35 sgb->count = 1; 36 } 37 status = B_OK; 38 } else { 39 TRACE_ALWAYS("init_sg_buffer fatal: not initialized!\n"); 40 } 41 return status; 42 } 43 44 /** 45 \fn:alloc_sg_buffer 46 TODO!!! 47 */ 48 status_t 49 realloc_sg_buffer(sg_buffer *sgb, size_t size) 50 { 51 status_t status = B_NO_INIT; 52 if(0 != sgb){ 53 /* NOTE: no check for previously allocations! May be dangerous!*/ 54 void *ptr = malloc(size); 55 status = (0 != ptr) ? B_OK : B_NO_MEMORY; 56 if(B_OK == status) { 57 memset(ptr, 0, size); 58 sgb->iov.iov_base = (iovec *)ptr; 59 sgb->iov.iov_len = size; 60 sgb->piov = &sgb->iov; 61 sgb->count = 1; 62 sgb->b_own = true; 63 status = B_OK; 64 } 65 } else { 66 TRACE_ALWAYS("realloc_sg_buffer fatal: not initialized!\n"); 67 } 68 return status; 69 } 70 71 status_t 72 sg_access_byte(sg_buffer *sgb, off_t offset, uchar *byte, bool b_set) 73 { 74 status_t status = B_ERROR; 75 int i = 0; 76 for(; i < sgb->count; i++){ 77 if(offset >= sgb->piov[i].iov_len){ 78 offset -= sgb->piov[i].iov_len; 79 } else { 80 uchar *ptr = (uchar *)sgb->piov[i].iov_base; 81 if(b_set){ 82 ptr[offset] = *byte; 83 }else{ 84 *byte = ptr[offset]; 85 } 86 status = B_OK; 87 break; 88 } 89 } 90 return status; 91 } 92 93 status_t 94 sg_memcpy(sg_buffer *d_sgb, off_t d_offset, 95 sg_buffer *s_sgb, off_t s_offset, size_t size) 96 { 97 status_t status = B_NO_INIT; 98 while(0 != d_sgb && 0 != s_sgb){ 99 uchar *d_ptr = 0; 100 uchar *s_ptr = 0; 101 status = B_ERROR; 102 if(1 == d_sgb->count){ 103 d_ptr = d_sgb->piov->iov_base + d_offset; 104 if((d_offset + size) > d_sgb->piov->iov_len){ 105 TRACE_ALWAYS("sg_memcpy fatal: dest buffer overflow: has:%d req:%d\n", 106 d_sgb->piov->iov_len, d_offset + size); 107 break; 108 } 109 } 110 if(1 == s_sgb->count){ 111 s_ptr = s_sgb->piov->iov_base + s_offset; 112 if((s_offset + size) > s_sgb->piov->iov_len){ 113 TRACE_ALWAYS("sg_memcpy fatal: src buffer overflow: has:%d req:%d\n", 114 s_sgb->piov->iov_len, s_offset + size); 115 break; 116 } 117 } 118 if(0 != d_ptr && 0 != s_ptr){ 119 memcpy(d_ptr, s_ptr, size); 120 } else { 121 uchar byte = 0; 122 int i = 0; 123 for(; i < size; i++){ 124 status = sg_access_byte(s_sgb, s_offset + i, &byte, false); 125 if(B_OK == status) 126 status = sg_access_byte(d_sgb, d_offset + i, &byte, true); 127 if(B_OK != status){ 128 TRACE_ALWAYS("sg_memcpy fatal: dest:%d src:%d size:%d/%d\n", 129 d_offset, s_offset, i, size); 130 break; 131 } 132 } 133 } 134 status = B_OK; 135 break; 136 } 137 if(B_NO_INIT == status) 138 TRACE_ALWAYS("sg_memcpy fatal: not initialized"); 139 return status; 140 } 141 142 /** 143 \fn:free_sg_buffer 144 TODO!!! 145 */ 146 void 147 free_sg_buffer(sg_buffer *sgb) 148 { 149 if(0 != sgb && sgb->b_own){ 150 int i = 0; 151 for(; i < sgb->count; i++){ 152 free(sgb->piov[i].iov_base); 153 } 154 memset(sgb, 0, sizeof(sg_buffer)); 155 } 156 } 157 158 status_t 159 sg_buffer_len(sg_buffer *sgb, size_t *size) 160 { 161 status_t status = B_NO_INIT; 162 if(0!=sgb && 0!=size){ 163 int i = 0; 164 *size = 0; 165 for(; i < sgb->count; i++){ 166 *size += sgb->piov[i].iov_len; 167 } 168 status = B_OK; 169 } else { 170 TRACE_ALWAYS("sg_buffer_len fatal: not initialized (sgb:%x/size:%x)", sgb, size); 171 } 172 return status; 173 } 174