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