1/* 2 * linux/drivers/acorn/scsi/scsi.h 3 * 4 * Copyright (C) 2002 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * Commonly used scsi driver functions. 11 */ 12 13#include <linux/scatterlist.h> 14 15#define BELT_AND_BRACES 16 17/* 18 * The scatter-gather list handling. This contains all 19 * the yucky stuff that needs to be fixed properly. 20 */ 21static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) 22{ 23 int bufs = SCp->buffers_residual; 24 25 BUG_ON(bufs + 1 > max); 26 27 sg_set_buf(sg, SCp->ptr, SCp->this_residual); 28 29 if (bufs) 30 memcpy(sg + 1, SCp->buffer + 1, 31 sizeof(struct scatterlist) * bufs); 32 return bufs + 1; 33} 34 35static inline int next_SCp(struct scsi_pointer *SCp) 36{ 37 int ret = SCp->buffers_residual; 38 if (ret) { 39 SCp->buffer++; 40 SCp->buffers_residual--; 41 SCp->ptr = (char *) 42 (page_address(SCp->buffer->page) + 43 SCp->buffer->offset); 44 SCp->this_residual = SCp->buffer->length; 45 } else { 46 SCp->ptr = NULL; 47 SCp->this_residual = 0; 48 } 49 return ret; 50} 51 52static inline unsigned char get_next_SCp_byte(struct scsi_pointer *SCp) 53{ 54 char c = *SCp->ptr; 55 56 SCp->ptr += 1; 57 SCp->this_residual -= 1; 58 59 return c; 60} 61 62static inline void put_next_SCp_byte(struct scsi_pointer *SCp, unsigned char c) 63{ 64 *SCp->ptr = c; 65 SCp->ptr += 1; 66 SCp->this_residual -= 1; 67} 68 69static inline void init_SCp(struct scsi_cmnd *SCpnt) 70{ 71 memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); 72 73 if (SCpnt->use_sg) { 74 unsigned long len = 0; 75 int buf; 76 77 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; 78 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; 79 SCpnt->SCp.ptr = (char *) 80 (page_address(SCpnt->SCp.buffer->page) + 81 SCpnt->SCp.buffer->offset); 82 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; 83 SCpnt->SCp.phase = SCpnt->request_bufflen; 84 85#ifdef BELT_AND_BRACES 86 /* 87 * Calculate correct buffer length. Some commands 88 * come in with the wrong request_bufflen. 89 */ 90 for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) 91 len += SCpnt->SCp.buffer[buf].length; 92 93 if (SCpnt->request_bufflen != len) 94 printk(KERN_WARNING "scsi%d.%c: bad request buffer " 95 "length %d, should be %ld\n", SCpnt->device->host->host_no, 96 '0' + SCpnt->device->id, SCpnt->request_bufflen, len); 97 SCpnt->request_bufflen = len; 98#endif 99 } else { 100 SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; 101 SCpnt->SCp.this_residual = SCpnt->request_bufflen; 102 SCpnt->SCp.phase = SCpnt->request_bufflen; 103 } 104 105 /* 106 * If the upper SCSI layers pass a buffer, but zero length, 107 * we aren't interested in the buffer pointer. 108 */ 109 if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { 110 SCpnt->SCp.ptr = NULL; 111 } 112} 113