#include "../../scsi/constants.h"
#include "acornscsi.h"
#include "msgqueue.h"
+#include "scsi.h"
#include <scsi/scsicam.h>
SCp->ptr += length;
SCp->this_residual -= length;
- if (!SCp->this_residual) {
- if (SCp->buffers_residual) {
- SCp->buffer++;
- SCp->buffers_residual--;
- SCp->ptr = (char *)SCp->buffer->address;
- SCp->this_residual = SCp->buffer->length;
- } else {
- SCp->ptr = NULL;
- host->dma.xfer_done = 1;
- }
- }
+ if (SCp->this_residual == 0 && next_SCp(SCp) == 0)
+ host->dma.xfer_done = 1;
}
/*
SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]);
SCpnt->SCp.sent_command = 0;
SCpnt->SCp.scsi_xferred = 0;
- SCpnt->SCp.Status = 0;
- SCpnt->SCp.Message = 0;
-
- if (SCpnt->use_sg) {
- SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
- SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
- SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;
- SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- } else {
- SCpnt->SCp.buffer = NULL;
- SCpnt->SCp.buffers_residual = 0;
- SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
- SCpnt->SCp.this_residual = SCpnt->request_bufflen;
- }
+
+ init_SCp(SCpnt);
host->stats.queues += 1;
#include "../../scsi/sd.h"
#include "../../scsi/hosts.h"
#include "fas216.h"
+#include "scsi.h"
#include <scsi/scsicam.h>
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
- int bufs = SCp->buffers_residual;
- int pci_dir, dma_dir, alatch_dir;
-
- if (bufs)
- memcpy(info->sg + 1, SCp->buffer + 1,
- sizeof(struct scatterlist) * bufs);
- info->sg[0].address = SCp->ptr;
- info->sg[0].page = NULL;
- info->sg[0].length = SCp->this_residual;
+ int bufs, pci_dir, dma_dir, alatch_dir;
+
+ bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
if (direction == DMA_OUT)
pci_dir = PCI_DMA_TODEVICE,
#include "../../scsi/sd.h"
#include "../../scsi/hosts.h"
#include "fas216.h"
+#include "scsi.h"
#include <scsi/scsicam.h>
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
- int bufs = SCp->buffers_residual;
- int pci_dir, dma_dir;
-
- if (bufs)
- memcpy(info->sg + 1, SCp->buffer + 1,
- sizeof(struct scatterlist) * bufs);
- info->sg[0].address = SCp->ptr;
- info->sg[0].page = NULL;
- info->sg[0].length = SCp->this_residual;
+ int bufs, pci_dir, dma_dir;
+
+ bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
if (direction == DMA_OUT)
pci_dir = PCI_DMA_TODEVICE,
#include "../../scsi/scsi.h"
#include "../../scsi/hosts.h"
#include "fas216.h"
+#include "scsi.h"
#define VER_MAJOR 0
#define VER_MINOR 0
static void
fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
{
- unsigned char *ptr;
- unsigned int residual;
+ Scsi_Pointer *SCp = &info->scsi.SCp;
fas216_checkmagic(info);
- ptr = info->scsi.SCp.ptr;
- residual = info->scsi.SCp.this_residual;
-
info->SCpnt->request_bufflen -= bytes_transferred;
- while (residual <= bytes_transferred && bytes_transferred) {
- /* We have used up this buffer */
- bytes_transferred -= residual;
- if (info->scsi.SCp.buffers_residual) {
- info->scsi.SCp.buffer++;
- info->scsi.SCp.buffers_residual--;
- ptr = (unsigned char *)info->scsi.SCp.buffer->address;
- residual = info->scsi.SCp.buffer->length;
- } else {
- ptr = NULL;
- residual = 0;
+ while (bytes_transferred != 0) {
+ if (SCp->this_residual > bytes_transferred)
+ break;
+ /*
+ * We have used up this buffer. Move on to the
+ * next buffer.
+ */
+ bytes_transferred -= SCp->this_residual;
+ if (!next_SCp(&info->scsi.SCp)) {
+ printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
+ info->host->host_no, '0' + info->SCpnt->target);
+ return;
}
}
- residual -= bytes_transferred;
- ptr += bytes_transferred;
-
- if (residual == 0)
- ptr = NULL;
-
- info->scsi.SCp.ptr = ptr;
- info->scsi.SCp.this_residual = residual;
+ SCp->this_residual -= bytes_transferred;
+ if (SCp->this_residual)
+ SCp->ptr += bytes_transferred;
+ else
+ SCp->ptr = NULL;
}
/* Function: void fas216_pio(FAS216_Info *info, fasdmadir_t direction)
static void
fas216_pio(FAS216_Info *info, fasdmadir_t direction)
{
- unsigned int residual;
- char *ptr;
-
fas216_checkmagic(info);
- residual = info->scsi.SCp.this_residual;
- ptr = info->scsi.SCp.ptr;
-
if (direction == DMA_OUT)
- outb(*ptr++, REG_FF(info));
+ outb(get_next_SCp_byte(&info->scsi.SCp), REG_FF(info));
else
- *ptr++ = inb(REG_FF(info));
-
- residual -= 1;
-
- if (residual == 0) {
- if (info->scsi.SCp.buffers_residual) {
- info->scsi.SCp.buffer++;
- info->scsi.SCp.buffers_residual--;
- ptr = (unsigned char *)info->scsi.SCp.buffer->address;
- residual = info->scsi.SCp.buffer->length;
- } else {
- ptr = NULL;
- residual = 0;
- }
- }
-
- info->scsi.SCp.ptr = ptr;
- info->scsi.SCp.this_residual = residual;
+ put_next_SCp_byte(&info->scsi.SCp, inb(REG_FF(info)));
}
/* Function: void fas216_starttransfer(FAS216_Info *info,
SCpnt->scsi_done = done;
SCpnt->host_scribble = (void *)fas216_std_done;
SCpnt->result = 0;
- SCpnt->SCp.Message = 0;
- SCpnt->SCp.Status = 0;
-
- if (SCpnt->use_sg) {
- unsigned long len = 0;
- int buf;
- SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
- SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
- SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;
- SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- /*
- * Calculate correct buffer length. Some commands
- * come in with the wrong request_bufflen.
- */
- for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
- len += SCpnt->SCp.buffer[buf].length;
-
- if (SCpnt->request_bufflen != len)
- printk(KERN_WARNING "scsi%d.%c: bad request buffer "
- "length %d, should be %ld\n", info->host->host_no,
- '0' + SCpnt->target, SCpnt->request_bufflen, len);
- SCpnt->request_bufflen = len;
- } else {
- SCpnt->SCp.buffer = NULL;
- SCpnt->SCp.buffers_residual = 0;
- SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
- SCpnt->SCp.this_residual = SCpnt->request_bufflen;
- }
-
- /*
- * If the upper SCSI layers pass a buffer, but zero length,
- * we aren't interested in the buffer pointer.
- */
- if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {
-#if 0
- printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "
- "command ", info->host->host_no, '0' + SCpnt->target);
- print_command(SCpnt->cmnd);
-#endif
- SCpnt->SCp.ptr = NULL;
- }
+ init_SCp(SCpnt);
info->stats.queues += 1;
SCpnt->tag = 0;
#include "../../scsi/sd.h"
#include "../../scsi/hosts.h"
#include "fas216.h"
+#include "scsi.h"
#include <scsi/scsicam.h>
if (dmach != NO_DMA &&
(min_type == fasdma_real_all || SCp->this_residual >= 512)) {
- int bufs = SCp->buffers_residual;
- int pci_dir, dma_dir;
-
- if (bufs)
- memcpy(info->sg + 1, SCp->buffer + 1,
- sizeof(struct scatterlist) * bufs);
- info->sg[0].address = SCp->ptr;
- info->sg[0].page = NULL;
- info->sg[0].length = SCp->this_residual;
+ int bufs, pci_dir, dma_dir;
+
+ bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG);
if (direction == DMA_OUT)
pci_dir = PCI_DMA_TODEVICE,
--- /dev/null
+/*
+ * linux/drivers/acorn/scsi/scsi.h
+ *
+ * Copyright (C) 2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Commonly used scsi driver functions.
+ */
+
+#define BELT_AND_BRACES
+
+/*
+ * The scatter-gather list handling. This contains all
+ * the yucky stuff that needs to be fixed properly.
+ */
+static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int max)
+{
+ int bufs = SCp->buffers_residual;
+
+ BUG_ON(bufs + 1 > max);
+
+ sg->page = virt_to_page(SCp->ptr);
+ sg->offset = ((unsigned int)SCp->ptr) & ~PAGE_MASK;
+ sg->length = SCp->this_residual;
+
+ if (bufs)
+ memcpy(sg + 1, SCp->buffer + 1,
+ sizeof(struct scatterlist) * bufs);
+ return bufs + 1;
+}
+
+static inline int next_SCp(Scsi_Pointer *SCp)
+{
+ int ret = SCp->buffers_residual;
+ if (ret) {
+ SCp->buffer++;
+ SCp->buffers_residual--;
+ SCp->ptr = (char *)
+ (page_address(SCp->buffer->page) +
+ SCp->buffer->offset);
+ SCp->this_residual = SCp->buffer->length;
+ } else {
+ SCp->ptr = NULL;
+ SCp->this_residual = 0;
+ }
+ return ret;
+}
+
+static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
+{
+ char c = SCp->ptr;
+
+ SCp->ptr += 1;
+ SCp->this_residual -= 1;
+ if (SCp->this_residual == 0)
+ next_SCp(SCp);
+
+ return c;
+}
+
+static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c)
+{
+ SCp->ptr = c;
+ SCp->ptr += 1;
+ SCp->this_residual -= 1;
+ if (SCp->this_residual == 0)
+ next_SCp(SCp);
+}
+
+static inline void init_SCp(Scsi_Cmnd *SCpnt)
+{
+ SCpnt->SCp.Message = 0;
+ SCpnt->SCp.Status = 0;
+
+ if (SCpnt->use_sg) {
+ unsigned long len = 0;
+ int buf;
+
+ SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
+ SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
+ SCpnt->SCp.ptr = (char *)
+ (page_address(SCpnt->SCp.buffer->page) +
+ SCpnt->SCp.buffer->offset);
+ SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
+
+#ifdef BELT_AND_BRACES
+ /*
+ * Calculate correct buffer length. Some commands
+ * come in with the wrong request_bufflen.
+ */
+ for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
+ len += SCpnt->SCp.buffer[buf].length;
+
+ if (SCpnt->request_bufflen != len)
+ printk(KERN_WARNING "scsi%d.%c: bad request buffer "
+ "length %d, should be %ld\n", SCpnt->host->host_no,
+ '0' + SCpnt->target, SCpnt->request_bufflen, len);
+ SCpnt->request_bufflen = len;
+#endif
+ } else {
+ SCpnt->SCp.buffer = NULL;
+ SCpnt->SCp.buffers_residual = 0;
+ SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
+ SCpnt->SCp.this_residual = SCpnt->request_bufflen;
+ }
+
+ /*
+ * If the upper SCSI layers pass a buffer, but zero length,
+ * we aren't interested in the buffer pointer.
+ */
+ if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {
+#ifdef BELT_AND_BRACES
+ printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "
+ "command ", SCpnt->host->host_no, '0' + SCpnt->target);
+ print_command(SCpnt->cmnd);
+#endif
+ SCpnt->SCp.ptr = NULL;
+ }
+}