18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/drivers/acorn/scsi/scsi.h 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2002 Russell King 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Commonly used scsi driver functions. 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/scatterlist.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define BELT_AND_BRACES 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * The scatter-gather list handling. This contains all 168c2ecf20Sopenharmony_ci * the yucky stuff that needs to be fixed properly. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max 218c2ecf20Sopenharmony_ci * entries of uninitialized memory. SCp is from scsi-ml and has a valid 228c2ecf20Sopenharmony_ci * (possibly chained) sg-list 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_cistatic inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci int bufs = SCp->buffers_residual; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg(). 298c2ecf20Sopenharmony_ci * and to remove this BUG_ON. Use min() in-its-place 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci BUG_ON(bufs + 1 > max); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci sg_set_buf(sg, SCp->ptr, SCp->this_residual); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci if (bufs) { 368c2ecf20Sopenharmony_ci struct scatterlist *src_sg; 378c2ecf20Sopenharmony_ci unsigned i; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i) 408c2ecf20Sopenharmony_ci *(++sg) = *src_sg; 418c2ecf20Sopenharmony_ci sg_mark_end(sg); 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci return bufs + 1; 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic inline int next_SCp(struct scsi_pointer *SCp) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci int ret = SCp->buffers_residual; 508c2ecf20Sopenharmony_ci if (ret) { 518c2ecf20Sopenharmony_ci SCp->buffer = sg_next(SCp->buffer); 528c2ecf20Sopenharmony_ci SCp->buffers_residual--; 538c2ecf20Sopenharmony_ci SCp->ptr = sg_virt(SCp->buffer); 548c2ecf20Sopenharmony_ci SCp->this_residual = SCp->buffer->length; 558c2ecf20Sopenharmony_ci } else { 568c2ecf20Sopenharmony_ci SCp->ptr = NULL; 578c2ecf20Sopenharmony_ci SCp->this_residual = 0; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci return ret; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic inline unsigned char get_next_SCp_byte(struct scsi_pointer *SCp) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci char c = *SCp->ptr; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci SCp->ptr += 1; 678c2ecf20Sopenharmony_ci SCp->this_residual -= 1; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci return c; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic inline void put_next_SCp_byte(struct scsi_pointer *SCp, unsigned char c) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci *SCp->ptr = c; 758c2ecf20Sopenharmony_ci SCp->ptr += 1; 768c2ecf20Sopenharmony_ci SCp->this_residual -= 1; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic inline void init_SCp(struct scsi_cmnd *SCpnt) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (scsi_bufflen(SCpnt)) { 848c2ecf20Sopenharmony_ci unsigned long len = 0; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci SCpnt->SCp.buffer = scsi_sglist(SCpnt); 878c2ecf20Sopenharmony_ci SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1; 888c2ecf20Sopenharmony_ci SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer); 898c2ecf20Sopenharmony_ci SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; 908c2ecf20Sopenharmony_ci SCpnt->SCp.phase = scsi_bufflen(SCpnt); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci#ifdef BELT_AND_BRACES 938c2ecf20Sopenharmony_ci { /* 948c2ecf20Sopenharmony_ci * Calculate correct buffer length. Some commands 958c2ecf20Sopenharmony_ci * come in with the wrong scsi_bufflen. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci struct scatterlist *sg; 988c2ecf20Sopenharmony_ci unsigned i, sg_count = scsi_sg_count(SCpnt); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci scsi_for_each_sg(SCpnt, sg, sg_count, i) 1018c2ecf20Sopenharmony_ci len += sg->length; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (scsi_bufflen(SCpnt) != len) { 1048c2ecf20Sopenharmony_ci printk(KERN_WARNING 1058c2ecf20Sopenharmony_ci "scsi%d.%c: bad request buffer " 1068c2ecf20Sopenharmony_ci "length %d, should be %ld\n", 1078c2ecf20Sopenharmony_ci SCpnt->device->host->host_no, 1088c2ecf20Sopenharmony_ci '0' + SCpnt->device->id, 1098c2ecf20Sopenharmony_ci scsi_bufflen(SCpnt), len); 1108c2ecf20Sopenharmony_ci /* 1118c2ecf20Sopenharmony_ci * FIXME: Totaly naive fixup. We should abort 1128c2ecf20Sopenharmony_ci * with error 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_ci SCpnt->SCp.phase = 1158c2ecf20Sopenharmony_ci min_t(unsigned long, len, 1168c2ecf20Sopenharmony_ci scsi_bufflen(SCpnt)); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci#endif 1208c2ecf20Sopenharmony_ci } else { 1218c2ecf20Sopenharmony_ci SCpnt->SCp.ptr = NULL; 1228c2ecf20Sopenharmony_ci SCpnt->SCp.this_residual = 0; 1238c2ecf20Sopenharmony_ci SCpnt->SCp.phase = 0; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci} 126