scsi.h revision ee0ca6bab394fe41a2b4de58c4532b09a41c9165
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/drivers/acorn/scsi/scsi.h 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2002 Russell King 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Commonly used scsi driver functions. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13378f058cc49bcda7fa63d3cd86d2f9a0a5188b1cDavid Hardeman#include <linux/scatterlist.h> 14378f058cc49bcda7fa63d3cd86d2f9a0a5188b1cDavid Hardeman 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BELT_AND_BRACES 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The scatter-gather list handling. This contains all 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the yucky stuff that needs to be fixed properly. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 210a04137e75204e370dbdf2376033853eea126de7Christoph Hellwigstatic inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max) 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int bufs = SCp->buffers_residual; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BUG_ON(bufs + 1 > max); 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 27378f058cc49bcda7fa63d3cd86d2f9a0a5188b1cDavid Hardeman sg_set_buf(sg, SCp->ptr, SCp->this_residual); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bufs) 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(sg + 1, SCp->buffer + 1, 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(struct scatterlist) * bufs); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return bufs + 1; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 350a04137e75204e370dbdf2376033853eea126de7Christoph Hellwigstatic inline int next_SCp(struct scsi_pointer *SCp) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = SCp->buffers_residual; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->buffer++; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->buffers_residual--; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->ptr = (char *) 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (page_address(SCp->buffer->page) + 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->buffer->offset); 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->this_residual = SCp->buffer->length; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->ptr = NULL; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->this_residual = 0; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 520a04137e75204e370dbdf2376033853eea126de7Christoph Hellwigstatic inline unsigned char get_next_SCp_byte(struct scsi_pointer *SCp) 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char c = *SCp->ptr; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->ptr += 1; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->this_residual -= 1; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return c; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 620a04137e75204e370dbdf2376033853eea126de7Christoph Hellwigstatic inline void put_next_SCp_byte(struct scsi_pointer *SCp, unsigned char c) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *SCp->ptr = c; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->ptr += 1; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCp->this_residual -= 1; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69ee0ca6bab394fe41a2b4de58c4532b09a41c9165Henrik Kretzschmarstatic inline void init_SCp(struct scsi_cmnd *SCpnt) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SCpnt->use_sg) { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long len = 0; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int buf; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 77574dc0abab6650c5371df15ac708e48fa25bed89Russell King SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.ptr = (char *) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (page_address(SCpnt->SCp.buffer->page) + 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.buffer->offset); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef BELT_AND_BRACES 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate correct buffer length. Some commands 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * come in with the wrong request_bufflen. 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len += SCpnt->SCp.buffer[buf].length; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SCpnt->request_bufflen != len) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "scsi%d.%c: bad request buffer " 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "length %d, should be %ld\n", SCpnt->device->host->host_no, 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds '0' + SCpnt->device->id, SCpnt->request_bufflen, len); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->request_bufflen = len; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.this_residual = SCpnt->request_bufflen; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If the upper SCSI layers pass a buffer, but zero length, 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we aren't interested in the buffer pointer. 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 //def BELT_AND_BRACES 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "command ", SCpnt->host->host_no, '0' + SCpnt->target); 111db9dff366ba78085d0323364fadbf09bec0e77ee<hch@lst.de> __scsi_print_command(SCpnt->cmnd); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCpnt->SCp.ptr = NULL; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 116