Commit b056db71 authored by Jamie Lenehan's avatar Jamie Lenehan Committed by James Bottomley

[PATCH] dc395x [2/5] - sg list handling cleanups

Cleanup a lot of the sg list handling to make it easier to follow in
preparation for making this work on sparc64 (big-endian & 64bit).
parent ba44f971
...@@ -210,11 +210,6 @@ static char tracebuf[64]; ...@@ -210,11 +210,6 @@ static char tracebuf[64];
#define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address)) #define DC395x_write16(acb,address,value) outw((value), acb->io_port_base + (address))
#define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address)) #define DC395x_write32(acb,address,value) outl((value), acb->io_port_base + (address))
#define BUS_ADDR(sg) sg_dma_address(&(sg))
#define CPU_ADDR(sg) (page_address((sg).page)+(sg).offset)
#define PAGE_ADDRESS(sg) page_address((sg)->page)
/* cmd->result */ /* cmd->result */
#define RES_TARGET 0x000000FF /* Target State */ #define RES_TARGET 0x000000FF /* Target State */
#define RES_TARGET_LNX STATUS_MASK /* Only official ... */ #define RES_TARGET_LNX STATUS_MASK /* Only official ... */
...@@ -233,6 +228,13 @@ static char tracebuf[64]; ...@@ -233,6 +228,13 @@ static char tracebuf[64];
#define TAG_NONE 255 #define TAG_NONE 255
/*
* srb->segement_x is the hw sg list. It is always allocated as a
* DC395x_MAX_SG_LISTENTRY entries in a linear block which does not
* cross a page boundy.
*/
#define SEGMENTX_LEN (sizeof(struct SGentry)*DC395x_MAX_SG_LISTENTRY)
struct SGentry { struct SGentry {
u32 address; /* bus! address */ u32 address; /* bus! address */
...@@ -276,21 +278,28 @@ struct NvRamType { ...@@ -276,21 +278,28 @@ struct NvRamType {
struct ScsiReqBlk { struct ScsiReqBlk {
struct list_head list; /* next/prev ptrs for srb lists */ struct list_head list; /* next/prev ptrs for srb lists */
struct DeviceCtlBlk *dcb; struct DeviceCtlBlk *dcb;
/* HW scatter list (up to 64 entries) */
struct SGentry *segment_x;
Scsi_Cmnd *cmd; Scsi_Cmnd *cmd;
unsigned char *virt_addr; /* set by update_sg_list */ struct SGentry *segment_x; /* Linear array of hw sg entries (up to 64 entries) */
u32 sg_bus_addr; /* Bus address of sg list (ie, of segment_x) */
u32 total_xfer_length; u8 sg_count; /* No of HW sg entries for this request */
u32 xferred; /* Backup for the already xferred len */ u8 sg_index; /* Index of HW sg entry for this request */
u32 total_xfer_length; /* Total number of bytes remaining to be transfered */
unsigned char *virt_addr; /* Virtual address of current transfer position */
u32 sg_bus_addr; /* bus address of DC395x scatterlist */ /*
* The sense buffer handling function, request_sense, uses
* the first hw sg entry (segment_x[0]) and the transfer
* length (total_xfer_length). While doing this it stores the
* original values into the last sg hw list
* (srb->segment_x[DC395x_MAX_SG_LISTENTRY - 1] and the
* total_xfer_length in xferred. These values are restored in
* pci_unmap_srb_sense. This is the only place xferred is used.
*/
u32 xferred; /* Saved copy of total_xfer_length */
u16 state; u16 state;
u8 sg_count;
u8 sg_index;
u8 msgin_buf[6]; u8 msgin_buf[6];
u8 msgout_buf[6]; u8 msgout_buf[6];
...@@ -835,7 +844,8 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb, ...@@ -835,7 +844,8 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb,
static void srb_waiting_append(struct DeviceCtlBlk *dcb, static void srb_waiting_append(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb) struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "srb_waiting_append: srb %p cmd %li\n", srb, srb->cmd->pid); dprintkdbg(DBG_0, "srb_waiting_append: srb %p cmd %li\n",
srb, srb->cmd->pid);
list_add_tail(&srb->list, &dcb->srb_waiting_list); list_add_tail(&srb->list, &dcb->srb_waiting_list);
} }
...@@ -879,7 +889,8 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb, ...@@ -879,7 +889,8 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb,
static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb) struct ScsiReqBlk *srb)
{ {
dprintkdbg(DBG_0, "srb_going_to_waiting_move: srb %p, pid = %li\n", srb, srb->cmd->pid); dprintkdbg(DBG_0, "srb_going_to_waiting_move: srb %p, pid = %li\n",
srb, srb->cmd->pid);
list_move(&srb->list, &dcb->srb_waiting_list); list_move(&srb->list, &dcb->srb_waiting_list);
} }
...@@ -1021,134 +1032,97 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) ...@@ -1021,134 +1032,97 @@ static void send_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb, static void build_srb(Scsi_Cmnd *cmd, struct DeviceCtlBlk *dcb,
struct ScsiReqBlk *srb) struct ScsiReqBlk *srb)
{ {
int i, max; int dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
struct SGentry *sgp;
struct scatterlist *sl;
u32 request_size;
int dir;
dprintkdbg(DBG_0, "build_srb...\n"); dprintkdbg(DBG_0, "build_srb...\n");
srb->dcb = dcb; srb->dcb = dcb;
srb->cmd = cmd; srb->cmd = cmd;
dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); srb->sg_count = 0;
srb->total_xfer_length = 0;
srb->sg_bus_addr = 0;
srb->virt_addr = 0;
srb->sg_index = 0;
srb->adapter_status = 0;
srb->target_status = 0;
srb->msg_count = 0;
srb->status = 0;
srb->flag = 0;
srb->state = 0;
srb->retry_count = 0;
srb->tag_number = TAG_NONE;
srb->scsi_phase = PH_BUS_FREE; /* initial phase */
srb->end_message = 0;
if (cmd->use_sg && dir != PCI_DMA_NONE) { if (dir == PCI_DMA_NONE || !cmd->request_buffer) {
unsigned int len = 0; dprintkdbg(DBG_0, "srb[A] len=%d buf=%p use_sg=%d !MAP=%08x\n",
/* TODO: In case usg_sg and the no of segments differ, things cmd->bufflen, cmd->request_buffer,
* will probably go wrong. */ cmd->use_sg, srb->segment_x[0].address);
max = srb->sg_count = } else if (cmd->use_sg) {
pci_map_sg(dcb->acb->dev, int i;
(struct scatterlist *)cmd->request_buffer, u32 reqlen = cmd->request_bufflen;
cmd->use_sg, dir); struct scatterlist *sl = (struct scatterlist *)
sgp = srb->segment_x; cmd->request_buffer;
request_size = cmd->request_bufflen; struct SGentry *sgp = srb->segment_x;
dprintkdbg(DBG_SGPARANOIA, srb->sg_count = pci_map_sg(dcb->acb->dev, sl, cmd->use_sg,
"BuildSRB: Bufflen = %d, buffer = %p, use_sg = %d\n", dir);
cmd->request_bufflen, cmd->request_buffer, dprintkdbg(DBG_0, "srb[B] len=%d buf=%p use_sg=%d segs=%d\n",
cmd->use_sg); reqlen, cmd->request_buffer, cmd->use_sg,
dprintkdbg(DBG_SGPARANOIA,
"Mapped %i Segments to %i\n", cmd->use_sg,
srb->sg_count); srb->sg_count);
sl = (struct scatterlist *)cmd->request_buffer;
srb->virt_addr = page_address(sl->page); srb->virt_addr = page_address(sl->page);
for (i = 0; i < max; i++) { for (i = 0; i < srb->sg_count; i++) {
u32 busaddr = (u32) sg_dma_address(&sl[i]); u32 busaddr = (u32)sg_dma_address(&sl[i]);
u32 seglen = (u32) sl[i].length; u32 seglen = (u32)sl[i].length;
sgp[i].address = busaddr; sgp[i].address = busaddr;
sgp[i].length = seglen; sgp[i].length = seglen;
len += seglen; srb->total_xfer_length += seglen;
dprintkdbg(DBG_SGPARANOIA,
"Setting up sgp %d, address = 0x%08x, length = %d, tot len = %d\n",
i, busaddr, seglen, len);
}
sgp += max - 1;
/* Fixup for last buffer too big as it is allocated on even page boundaries */
if (len > request_size) {
#if debug_enabled(DBG_KG) || debug_enabled(DBG_SGPARANOIA)
dprintkdbg(DBG_KG|DBG_SGPARANOIA,
"Fixup SG total length: %d->%d, last seg %d->%d\n",
len, request_size, sgp->length,
sgp->length - (len - request_size));
#endif
sgp->length -= (len - request_size);
len = request_size;
} }
/* WIDE padding */ sgp += srb->sg_count - 1;
if (dcb->sync_period & WIDE_SYNC && len % 2) {
len++; /*
* adjust last page if too big as it is allocated
* on even page boundaries
*/
if (srb->total_xfer_length > reqlen) {
sgp->length -= (srb->total_xfer_length - reqlen);
srb->total_xfer_length = reqlen;
}
/* Fixup for WIDE padding - make sure length is even */
if (dcb->sync_period & WIDE_SYNC &&
srb->total_xfer_length % 2) {
srb->total_xfer_length++;
sgp->length++; sgp->length++;
} }
srb->total_xfer_length = len; /*? */
/* Hopefully this does not cross a page boundary ... */ srb->sg_bus_addr = pci_map_single(dcb->acb->dev,
srb->sg_bus_addr =
pci_map_single(dcb->acb->dev, srb->segment_x,
sizeof(struct SGentry) *
DC395x_MAX_SG_LISTENTRY,
PCI_DMA_TODEVICE);
dprintkdbg(DBG_SGPARANOIA,
"Map SG descriptor list %p (%05x) to %08x\n",
srb->segment_x, srb->segment_x,
sizeof(struct SGentry) * DC395x_MAX_SG_LISTENTRY, SEGMENTX_LEN,
srb->sg_bus_addr); PCI_DMA_TODEVICE);
dprintkdbg(DBG_SGPARANOIA, "srb[B] map sg %p->%08x(%05x)\n",
srb->segment_x, srb->sg_bus_addr, SEGMENTX_LEN);
} else { } else {
if (cmd->request_buffer && dir != PCI_DMA_NONE) { srb->total_xfer_length = cmd->request_bufflen;
u32 len = cmd->request_bufflen; /* Actual request size */
srb->sg_count = 1; srb->sg_count = 1;
srb->segment_x[0].address = srb->segment_x[0].address =
pci_map_single(dcb->acb->dev, pci_map_single(dcb->acb->dev, cmd->request_buffer,
cmd->request_buffer, len, dir); srb->total_xfer_length, dir);
/* WIDE padding */
if (dcb->sync_period & WIDE_SYNC && len % 2)
len++;
srb->segment_x[0].length = len;
srb->total_xfer_length = len;
srb->virt_addr = cmd->request_buffer;
srb->sg_bus_addr = 0;
dprintkdbg(DBG_SGPARANOIA,
"BuildSRB: len = %d, buffer = %p, use_sg = %d, map %08x\n",
len, cmd->request_buffer, cmd->use_sg,
srb->segment_x[0].address);
} else {
srb->sg_count = 0;
srb->total_xfer_length = 0;
srb->sg_bus_addr = 0;
srb->virt_addr = 0;
dprintkdbg(DBG_SGPARANOIA,
"BuildSRB: buflen = %d, buffer = %p, use_sg = %d, NOMAP %08x\n",
cmd->bufflen, cmd->request_buffer,
cmd->use_sg, srb->segment_x[0].address);
}
}
srb->sg_index = 0; /* Fixup for WIDE padding - make sure length is even */
srb->adapter_status = 0; if (dcb->sync_period & WIDE_SYNC && srb->total_xfer_length % 2)
srb->target_status = 0; srb->total_xfer_length++;
srb->msg_count = 0;
srb->status = 0;
srb->flag = 0;
srb->state = 0;
srb->retry_count = 0;
#if debug_enabled(DBG_TRACE|DBG_TRACEALL) && debug_enabled(DBG_SGPARANOIA) srb->segment_x[0].length = srb->total_xfer_length;
if ((unsigned long)srb->debugtrace & (DEBUGTRACEBUFSZ - 1)) { srb->virt_addr = cmd->request_buffer;
dprintkdbg(DBG_SGPARANOIA, dprintkdbg(DBG_0, "srb[C] len=%d buf=%p use_sg=%d map=%08x\n",
"SRB %i (%p): debugtrace %p corrupt!\n", srb->total_xfer_length, cmd->request_buffer,
(srb - dcb->acb->srb_array) / cmd->use_sg, srb->segment_x[0].address);
sizeof(struct ScsiReqBlk), srb, srb->debugtrace);
} }
#endif
#if debug_enabled(DBG_TRACE|DBG_TRACEALL) #if debug_enabled(DBG_TRACE|DBG_TRACEALL)
srb->debugpos = 0; srb->debugpos = 0;
srb->debugtrace = 0; srb->debugtrace = 0;
#endif #endif
TRACEPRINTF("pid %li(%li):%02x %02x..(%i-%i) *", cmd->pid,
jiffies, cmd->cmnd[0], cmd->cmnd[1],
cmd->device->id, cmd->device->lun);
srb->tag_number = TAG_NONE;
srb->scsi_phase = PH_BUS_FREE; /* initial phase */
srb->end_message = 0;
} }
...@@ -1598,7 +1572,7 @@ static u8 start_scsi(struct AdapterCtlBlk * acb, struct DeviceCtlBlk * dcb, ...@@ -1598,7 +1572,7 @@ static u8 start_scsi(struct AdapterCtlBlk * acb, struct DeviceCtlBlk * dcb,
u8 s_stat, scsicommand, i, identify_message; u8 s_stat, scsicommand, i, identify_message;
u8 *ptr; u8 *ptr;
dprintkdbg(DBG_0, "start_scsi..............\n"); dprintkdbg(DBG_0, "start_scsi (#%li)\n", srb->cmd->pid);
srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */ srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */
s_stat = DC395x_read8(acb, TRM_S1040_SCSI_SIGNAL); s_stat = DC395x_read8(acb, TRM_S1040_SCSI_SIGNAL);
...@@ -1958,7 +1932,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id, ...@@ -1958,7 +1932,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id,
static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "msgout_phase0...\n"); dprintkdbg(DBG_0, "msgout_phase0 (#%li)\n", srb->cmd->pid);
if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT))
*pscsi_status = PH_BUS_FREE; /*.. initial phase */ *pscsi_status = PH_BUS_FREE; /*.. initial phase */
...@@ -1974,7 +1948,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -1974,7 +1948,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 i; u16 i;
u8 *ptr; u8 *ptr;
dprintkdbg(DBG_0, "msgout_phase1...\n"); dprintkdbg(DBG_0, "msgout_phase1 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("MOP1*"); TRACEPRINTF("MOP1*");
clear_fifo(acb, "MOP1"); clear_fifo(acb, "MOP1");
if (!(srb->state & SRB_MSGOUT)) { if (!(srb->state & SRB_MSGOUT)) {
...@@ -2014,6 +1988,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2014,6 +1988,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "command_phase0 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("COP0 *"); TRACEPRINTF("COP0 *");
/*1.25 */ /*1.25 */
/*clear_fifo(acb, COP0); */ /*clear_fifo(acb, COP0); */
...@@ -2028,7 +2003,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2028,7 +2003,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u8 *ptr; u8 *ptr;
u16 i; u16 i;
dprintkdbg(DBG_0, "command_phase1...\n"); dprintkdbg(DBG_0, "command_phase1 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("COP1*"); TRACEPRINTF("COP1*");
clear_fifo(acb, "COP1"); clear_fifo(acb, "COP1");
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN);
...@@ -2058,8 +2033,11 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2058,8 +2033,11 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
} }
/* Do sanity checks for S/G list */ /*
static inline void check_sg_list(struct ScsiReqBlk *srb) * Verify that the remaining space in the hw sg lists is the same as
* the count of remaining bytes in srb->total_xfer_length
*/
static void sg_verify_length(struct ScsiReqBlk *srb)
{ {
if (debug_enabled(DBG_SGPARANOIA)) { if (debug_enabled(DBG_SGPARANOIA)) {
unsigned len = 0; unsigned len = 0;
...@@ -2079,75 +2057,90 @@ static inline void check_sg_list(struct ScsiReqBlk *srb) ...@@ -2079,75 +2057,90 @@ static inline void check_sg_list(struct ScsiReqBlk *srb)
* Compute the next Scatter Gather list index and adjust its length * Compute the next Scatter Gather list index and adjust its length
* and address if necessary; also compute virt_addr * and address if necessary; also compute virt_addr
*/ */
static void update_sg_list(struct ScsiReqBlk *srb, u32 left) static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
{ {
struct SGentry *psge;
u32 xferred = 0;
u8 idx; u8 idx;
Scsi_Cmnd *cmd = srb->cmd;
struct scatterlist *sg; struct scatterlist *sg;
Scsi_Cmnd *cmd = srb->cmd;
int segment = cmd->use_sg; int segment = cmd->use_sg;
u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
struct SGentry *psge = srb->segment_x + srb->sg_index;
dprintkdbg(DBG_0, "sg_update_list: Transfered %i of %i bytes, "
"%i remain\n",
xferred, srb->total_xfer_length, left);
if (xferred == 0) {
/* nothing to update since we did not transfer any data */
return;
}
dprintkdbg(DBG_KG, "Update SG: Total %i, Left %i\n", sg_verify_length(srb);
srb->total_xfer_length, left); srb->total_xfer_length = left; /* update remaining count */
check_sg_list(srb);
psge = srb->segment_x + srb->sg_index;
/* data that has already been transferred */
xferred = srb->total_xfer_length - left;
if (srb->total_xfer_length != left) {
/*check_sg_list_TX (srb, xferred); */
/* Remaining */
srb->total_xfer_length = left;
/* parsing from last time disconnect SGIndex */
for (idx = srb->sg_index; idx < srb->sg_count; idx++) { for (idx = srb->sg_index; idx < srb->sg_count; idx++) {
if (xferred >= psge->length) {
/* Complete SG entries done */ /* Complete SG entries done */
if (xferred >= psge->length)
xferred -= psge->length; xferred -= psge->length;
/* Partial SG entries done */ } else {
else { /* Partial SG entry done */
psge->length -= xferred; /* residue data length */ psge->length -= xferred;
psge->address += xferred; /* residue data pointer */ psge->address += xferred;
srb->sg_index = idx; srb->sg_index = idx;
pci_dma_sync_single(srb->dcb-> pci_dma_sync_single(srb->dcb->
acb->dev, acb->dev,
srb->sg_bus_addr, srb->sg_bus_addr,
sizeof(struct SGentry) SEGMENTX_LEN,
*
DC395x_MAX_SG_LISTENTRY,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
break; break;
} }
psge++; psge++;
} }
check_sg_list(srb); sg_verify_length(srb);
}
/* We need the corresponding virtual address sg_to_virt */ /* we need the corresponding virtual address */
/*dprintkl(KERN_DEBUG, "sg_to_virt: bus %08x -> virt ", psge->address); */
if (!segment) { if (!segment) {
srb->virt_addr += xferred; srb->virt_addr += xferred;
/*printk("%p\n", srb->virt_addr); */
return; return;
} }
/* We have to walk the scatterlist to find it */ /* We have to walk the scatterlist to find it */
sg = (struct scatterlist *)cmd->request_buffer; sg = (struct scatterlist *)cmd->request_buffer;
while (segment--) { while (segment--) {
/*printk("(%08x)%p ", BUS_ADDR(*sg), PAGE_ADDRESS(sg)); */
unsigned long mask = unsigned long mask =
~((unsigned long)sg->length - 1) & PAGE_MASK; ~((unsigned long)sg->length - 1) & PAGE_MASK;
if ((BUS_ADDR(*sg) & mask) == (psge->address & mask)) { if ((sg_dma_address(sg) & mask) == (psge->address & mask)) {
srb->virt_addr = (PAGE_ADDRESS(sg) srb->virt_addr = (page_address(sg->page)
+ psge->address - + psge->address -
(psge->address & PAGE_MASK)); (psge->address & PAGE_MASK));
/*printk("%p\n", srb->virt_addr); */
return; return;
} }
++sg; ++sg;
} }
dprintkl(KERN_ERR, "sg_to_virt failed!\n"); dprintkl(KERN_ERR, "sg_to_virt failed!\n");
srb->virt_addr = 0; srb->virt_addr = 0;
} }
/*
* We have transfered a single byte (PIO mode?) and need to update
* the count of bytes remaining (total_xfer_length) and update the sg
* entry to either point to next byte in the current sg entry, or of
* already at the end to point to the start of the next sg entry
*/
static void sg_subtract_one(struct ScsiReqBlk *srb)
{
srb->total_xfer_length--;
srb->segment_x[srb->sg_index].length--;
if (srb->total_xfer_length &&
!srb->segment_x[srb->sg_index].length) {
if (debug_enabled(DBG_PIO))
printk(" (next segment)");
srb->sg_index++;
sg_update_list(srb, srb->total_xfer_length);
}
}
/* /*
* cleanup_after_transfer * cleanup_after_transfer
* *
...@@ -2190,7 +2183,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2190,7 +2183,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 scsi_status = *pscsi_status; u16 scsi_status = *pscsi_status;
u32 d_left_counter = 0; u32 d_left_counter = 0;
dprintkdbg(DBG_0, "data_out_phase0...\n"); dprintkdbg(DBG_0, "data_out_phase0 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("DOP0*"); TRACEPRINTF("DOP0*");
/* /*
...@@ -2310,7 +2303,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2310,7 +2303,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
srb->total_xfer_length - d_left_counter; srb->total_xfer_length - d_left_counter;
const int diff = const int diff =
(dcb->sync_period & WIDE_SYNC) ? 2 : 1; (dcb->sync_period & WIDE_SYNC) ? 2 : 1;
update_sg_list(srb, d_left_counter); sg_update_list(srb, d_left_counter);
/* KG: Most ugly hack! Apparently, this works around a chip bug */ /* KG: Most ugly hack! Apparently, this works around a chip bug */
if ((srb->segment_x[srb->sg_index].length == if ((srb->segment_x[srb->sg_index].length ==
diff && srb->cmd->use_sg) diff && srb->cmd->use_sg)
...@@ -2321,7 +2314,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2321,7 +2314,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
"Work around chip bug (%i)?\n", diff); "Work around chip bug (%i)?\n", diff);
d_left_counter = d_left_counter =
srb->total_xfer_length - diff; srb->total_xfer_length - diff;
update_sg_list(srb, d_left_counter); sg_update_list(srb, d_left_counter);
/*srb->total_xfer_length -= diff; */ /*srb->total_xfer_length -= diff; */
/*srb->virt_addr += diff; */ /*srb->virt_addr += diff; */
/*if (srb->cmd->use_sg) */ /*if (srb->cmd->use_sg) */
...@@ -2351,7 +2344,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2351,7 +2344,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "data_out_phase1...\n"); dprintkdbg(DBG_0, "data_out_phase1 (#%li)\n", srb->cmd->pid);
/*1.25 */ /*1.25 */
TRACEPRINTF("DOP1*"); TRACEPRINTF("DOP1*");
clear_fifo(acb, "DOP1"); clear_fifo(acb, "DOP1");
...@@ -2368,7 +2361,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2368,7 +2361,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 scsi_status = *pscsi_status; u16 scsi_status = *pscsi_status;
u32 d_left_counter = 0; u32 d_left_counter = 0;
dprintkdbg(DBG_0, "data_in_phase0...\n"); dprintkdbg(DBG_0, "data_in_phase0 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("DIP0*"); TRACEPRINTF("DIP0*");
/* /*
...@@ -2445,7 +2438,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2445,7 +2438,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
if (d_left_counter if (d_left_counter
&& srb->total_xfer_length <= DC395x_LASTPIO) { && srb->total_xfer_length <= DC395x_LASTPIO) {
/*u32 addr = (srb->segment_x[srb->sg_index].address); */ /*u32 addr = (srb->segment_x[srb->sg_index].address); */
/*update_sg_list (srb, d_left_counter); */ /*sg_update_list (srb, d_left_counter); */
dprintkdbg(DBG_PIO, "DIP0: PIO (%i %s) to %p for remaining %i bytes:", dprintkdbg(DBG_PIO, "DIP0: PIO (%i %s) to %p for remaining %i bytes:",
DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) & DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) &
0x1f, 0x1f,
...@@ -2458,32 +2451,19 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2458,32 +2451,19 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
CFG2_WIDEFIFO); CFG2_WIDEFIFO);
while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != while (DC395x_read8(acb, TRM_S1040_SCSI_FIFOCNT) != 0x40) {
0x40) { u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
u8 byte =
DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
*(srb->virt_addr)++ = byte; *(srb->virt_addr)++ = byte;
if (debug_enabled(DBG_PIO)) if (debug_enabled(DBG_PIO))
printk(" %02x", byte); printk(" %02x", byte);
srb->total_xfer_length--;
d_left_counter--; d_left_counter--;
srb->segment_x[srb->sg_index].length--; sg_subtract_one(srb);
if (srb->total_xfer_length
&& !srb->segment_x[srb->sg_index].
length) {
if (debug_enabled(DBG_PIO))
printk(" (next segment)");
srb->sg_index++;
update_sg_list(srb,
d_left_counter);
}
} }
if (srb->dcb->sync_period & WIDE_SYNC) { if (srb->dcb->sync_period & WIDE_SYNC) {
#if 1 /* Read the last byte ... */ #if 1
/* Read the last byte ... */
if (srb->total_xfer_length > 0) { if (srb->total_xfer_length > 0) {
u8 byte = u8 byte = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
DC395x_read8
(acb, TRM_S1040_SCSI_FIFO);
*(srb->virt_addr)++ = byte; *(srb->virt_addr)++ = byte;
srb->total_xfer_length--; srb->total_xfer_length--;
if (debug_enabled(DBG_PIO)) if (debug_enabled(DBG_PIO))
...@@ -2563,7 +2543,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2563,7 +2543,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
* there were some data residue in SCSI FIFO or * there were some data residue in SCSI FIFO or
* SCSI transfer counter not empty * SCSI transfer counter not empty
*/ */
update_sg_list(srb, d_left_counter); sg_update_list(srb, d_left_counter);
} }
} }
/* KG: The target may decide to disconnect: Empty FIFO before! */ /* KG: The target may decide to disconnect: Empty FIFO before! */
...@@ -2597,7 +2577,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2597,7 +2577,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "data_in_phase1...\n"); dprintkdbg(DBG_0, "data_in_phase1 (#%li)\n", srb->cmd->pid);
/* FIFO should be cleared, if previous phase was not DataPhase */ /* FIFO should be cleared, if previous phase was not DataPhase */
/*clear_fifo(acb, "DIP1"); */ /*clear_fifo(acb, "DIP1"); */
/* Allow data in! */ /* Allow data in! */
...@@ -2615,7 +2595,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2615,7 +2595,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
struct DeviceCtlBlk *dcb = srb->dcb; struct DeviceCtlBlk *dcb = srb->dcb;
u8 bval; u8 bval;
dprintkdbg(DBG_0, "DataIO_transfer %c (pid %li): len = %i, SG: %i/%i\n", dprintkdbg(DBG_0, "data_io_transfer %c (#%li): len=%i, sg=(%i/%i)\n",
((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->cmd->pid, ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->cmd->pid,
srb->total_xfer_length, srb->sg_index, srb->total_xfer_length, srb->sg_index,
srb->sg_count); srb->sg_count);
...@@ -2623,7 +2603,12 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2623,7 +2603,12 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
srb->sg_index, srb->sg_count); srb->sg_index, srb->sg_count);
if (srb == acb->tmp_srb) if (srb == acb->tmp_srb)
dprintkl(KERN_ERR, "Using tmp_srb in DataPhase!\n"); dprintkl(KERN_ERR, "Using tmp_srb in DataPhase!\n");
if (srb->sg_index < srb->sg_count) {
if (srb->sg_index >= srb->sg_count) {
/* can't happen? out of bounds error */
return;
}
if (srb->total_xfer_length > DC395x_LASTPIO) { if (srb->total_xfer_length > DC395x_LASTPIO) {
u8 dma_status = DC395x_read8(acb, TRM_S1040_DMA_STATUS); u8 dma_status = DC395x_read8(acb, TRM_S1040_DMA_STATUS);
/* /*
...@@ -2633,13 +2618,12 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2633,13 +2618,12 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
if (dma_status & XFERPENDING) { if (dma_status & XFERPENDING) {
dprintkl(KERN_DEBUG, "Xfer pending! Expect trouble!!\n"); dprintkl(KERN_DEBUG, "Xfer pending! Expect trouble!!\n");
dump_register_info(acb, dcb, srb); dump_register_info(acb, dcb, srb);
DC395x_write8(acb, TRM_S1040_DMA_CONTROL, DC395x_write8(acb, TRM_S1040_DMA_CONTROL, CLRXFIFO);
CLRXFIFO);
} }
/* clear_fifo(acb, "IO"); */ /* clear_fifo(acb, "IO"); */
/* /*
* load what physical address of Scatter/Gather list table want to be * load what physical address of Scatter/Gather list table
* transfer * want to be transfer
*/ */
srb->state |= SRB_DATA_XFER; srb->state |= SRB_DATA_XFER;
DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0); DC395x_write32(acb, TRM_S1040_DMA_XHIGHADDR, 0);
...@@ -2649,10 +2633,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2649,10 +2633,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
srb->sg_bus_addr + srb->sg_bus_addr +
sizeof(struct SGentry) * sizeof(struct SGentry) *
srb->sg_index); srb->sg_index);
/* load how many bytes in the Scatter/Gather list table */ /* load how many bytes in the sg list table */
DC395x_write32(acb, TRM_S1040_DMA_XCNT, DC395x_write32(acb, TRM_S1040_DMA_XCNT,
((u32) ((u32)(srb->sg_count -
(srb->sg_count -
srb->sg_index) << 3)); srb->sg_index) << 3));
} else { /* without S/G */ } else { /* without S/G */
io_dir &= ~DMACMD_SG; io_dir &= ~DMACMD_SG;
...@@ -2668,11 +2651,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2668,11 +2651,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
if (io_dir & DMACMD_DIR) { /* read */ if (io_dir & DMACMD_DIR) { /* read */
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, DC395x_write8(acb, TRM_S1040_SCSI_COMMAND,
SCMD_DMA_IN); SCMD_DMA_IN);
DC395x_write16(acb, TRM_S1040_DMA_COMMAND, DC395x_write16(acb, TRM_S1040_DMA_COMMAND, io_dir);
io_dir);
} else { } else {
DC395x_write16(acb, TRM_S1040_DMA_COMMAND, DC395x_write16(acb, TRM_S1040_DMA_COMMAND, io_dir);
io_dir);
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, DC395x_write8(acb, TRM_S1040_SCSI_COMMAND,
SCMD_DMA_OUT); SCMD_DMA_OUT);
} }
...@@ -2680,10 +2661,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2680,10 +2661,9 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
} }
#if DC395x_LASTPIO #if DC395x_LASTPIO
else if (srb->total_xfer_length > 0) { /* The last four bytes: Do PIO */ else if (srb->total_xfer_length > 0) { /* The last four bytes: Do PIO */
/* clear_fifo(acb, "IO"); */
/* /*
* load what physical address of Scatter/Gather list table want to be * load what physical address of Scatter/Gather list table
* transfer * want to be transfer
*/ */
srb->state |= SRB_DATA_XFER; srb->state |= SRB_DATA_XFER;
/* load total transfer length (24bits) max value 16Mbyte */ /* load total transfer length (24bits) max value 16Mbyte */
...@@ -2696,31 +2676,21 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2696,31 +2676,21 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
} else { /* write */ } else { /* write */
int ln = srb->total_xfer_length; int ln = srb->total_xfer_length;
if (srb->dcb->sync_period & WIDE_SYNC) if (srb->dcb->sync_period & WIDE_SYNC)
DC395x_write8 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
(acb, TRM_S1040_SCSI_CONFIG2,
CFG2_WIDEFIFO); CFG2_WIDEFIFO);
dprintkdbg(DBG_PIO, "DOP1: PIO %i bytes from %p:", dprintkdbg(DBG_PIO, "DOP1: PIO %i bytes from %p:",
srb->total_xfer_length, srb->total_xfer_length,
srb->virt_addr); srb->virt_addr);
while (srb->total_xfer_length) { while (srb->total_xfer_length) {
if (debug_enabled(DBG_PIO)) if (debug_enabled(DBG_PIO))
printk(" %02x", (unsigned char) *(srb->virt_addr)); printk(" %02x", (unsigned char) *(srb->virt_addr));
DC395x_write8
(acb, TRM_S1040_SCSI_FIFO, DC395x_write8(acb, TRM_S1040_SCSI_FIFO,
*(srb->virt_addr)++); *(srb->virt_addr)++);
srb->total_xfer_length--;
srb->segment_x[srb->sg_index]. sg_subtract_one(srb);
length--;
if (srb->total_xfer_length
&& !srb->segment_x[srb->
sg_index].
length) {
if (debug_enabled(DBG_PIO))
printk(" (next segment)");
srb->sg_index++;
update_sg_list(srb,
srb->total_xfer_length);
}
} }
if (srb->dcb->sync_period & WIDE_SYNC) { if (srb->dcb->sync_period & WIDE_SYNC) {
if (ln % 2) { if (ln % 2) {
...@@ -2728,8 +2698,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2728,8 +2698,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
if (debug_enabled(DBG_PIO)) if (debug_enabled(DBG_PIO))
printk(" |00"); printk(" |00");
} }
DC395x_write8 DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
(acb, TRM_S1040_SCSI_CONFIG2, 0);
} }
/*DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, ln); */ /*DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, ln); */
if (debug_enabled(DBG_PIO)) if (debug_enabled(DBG_PIO))
...@@ -2754,53 +2723,39 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, ...@@ -2754,53 +2723,39 @@ static void data_io_transfer(struct AdapterCtlBlk *acb,
DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 2); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 2);
DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2,
CFG2_WIDEFIFO); CFG2_WIDEFIFO);
if (io_dir & DMACMD_DIR) { /* read */ if (io_dir & DMACMD_DIR) {
data = data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
DC395x_read8 data2 = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
(acb, TRM_S1040_SCSI_FIFO);
data2 =
DC395x_read8
(acb, TRM_S1040_SCSI_FIFO);
/*dprintkl(KERN_DEBUG, "DataIO: Xfer pad: %02x %02x\n", data, data2); */
} else { } else {
/* Danger, Robinson: If you find KGs scattered over the wide /* Danger, Robinson: If you find KGs
* disk, the driver or chip is to blame :-( */ * scattered over the wide disk, the driver
DC395x_write8(acb, TRM_S1040_SCSI_FIFO, * or chip is to blame :-( */
'K'); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'K');
DC395x_write8(acb, TRM_S1040_SCSI_FIFO, DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'G');
'G');
} }
DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0); DC395x_write8(acb, TRM_S1040_SCSI_CONFIG2, 0);
} else { } else {
DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
/* Danger, Robinson: If you find a collection of Ks on your disk /* Danger, Robinson: If you find a collection of Ks on your disk
* something broke :-( */ * something broke :-( */
if (io_dir & DMACMD_DIR) { /* read */ if (io_dir & DMACMD_DIR)
data = data = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
DC395x_read8 else
(acb, TRM_S1040_SCSI_FIFO); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, 'K');
/*dprintkl(KERN_DEBUG, "DataIO: Xfer pad: %02x\n", data); */
} else {
DC395x_write8(acb, TRM_S1040_SCSI_FIFO,
'K');
}
} }
srb->state |= SRB_XFERPAD; srb->state |= SRB_XFERPAD;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */
/* SCSI command */ /* SCSI command */
bval = bval = (io_dir & DMACMD_DIR) ? SCMD_FIFO_IN : SCMD_FIFO_OUT;
(io_dir & DMACMD_DIR) ? SCMD_FIFO_IN :
SCMD_FIFO_OUT;
DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, bval); DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, bval);
} }
}
} }
static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "StatusPhase0 (pid %li)\n", srb->cmd->pid); dprintkdbg(DBG_0, "status_phase0 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("STP0 *"); TRACEPRINTF("STP0 *");
srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */
...@@ -2817,10 +2772,8 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -2817,10 +2772,8 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "StatusPhase1 (pid=%li)\n", srb->cmd->pid); dprintkdbg(DBG_0, "status_phase1 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("STP1 *"); TRACEPRINTF("STP1 *");
/* Cleanup is now done at the end of DataXXPhase0 */
/*cleanup_after_transfer (acb, srb); */
srb->state = SRB_STATUS; srb->state = SRB_STATUS;
DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */
...@@ -2900,7 +2853,8 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, ...@@ -2900,7 +2853,8 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb,
struct ScsiReqBlk *srb = NULL; struct ScsiReqBlk *srb = NULL;
struct ScsiReqBlk *i; struct ScsiReqBlk *i;
dprintkdbg(DBG_0, "QTag Msg (SRB %p): %i\n", srb, tag); dprintkdbg(DBG_0, "msgin_qtag (#%li) tag=%i (srb=%p)\n",
srb->cmd->pid, tag, srb);
if (!(dcb->tag_mask & (1 << tag))) if (!(dcb->tag_mask & (1 << tag)))
dprintkl(KERN_DEBUG, dprintkl(KERN_DEBUG,
"MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n", "MsgIn_QTag: tag_mask (%08x) does not reserve tag %i!\n",
...@@ -3147,7 +3101,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -3147,7 +3101,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
{ {
struct DeviceCtlBlk *dcb = acb->active_dcb; struct DeviceCtlBlk *dcb = acb->active_dcb;
dprintkdbg(DBG_0, "msgin_phase0...\n"); dprintkdbg(DBG_0, "msgin_phase0 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("MIP0*"); TRACEPRINTF("MIP0*");
srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO);
...@@ -3275,7 +3229,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, ...@@ -3275,7 +3229,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb,
u16 *pscsi_status) u16 *pscsi_status)
{ {
dprintkdbg(DBG_0, "msgin_phase1...\n"); dprintkdbg(DBG_0, "msgin_phase1 (#%li)\n", srb->cmd->pid);
TRACEPRINTF("MIP1 *"); TRACEPRINTF("MIP1 *");
clear_fifo(acb, "MIP1"); clear_fifo(acb, "MIP1");
DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1);
...@@ -3344,7 +3298,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3344,7 +3298,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
} }
srb = dcb->active_srb; srb = dcb->active_srb;
acb->active_dcb = NULL; acb->active_dcb = NULL;
dprintkdbg(DBG_0, "Disconnect (pid=%li)\n", srb->cmd->pid); dprintkdbg(DBG_0, "disconnect (#%li)\n", srb->cmd->pid);
TRACEPRINTF("DISC *"); TRACEPRINTF("DISC *");
srb->scsi_phase = PH_BUS_FREE; /* initial phase */ srb->scsi_phase = PH_BUS_FREE; /* initial phase */
...@@ -3383,7 +3337,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3383,7 +3337,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
/* Normal selection timeout */ /* Normal selection timeout */
TRACEPRINTF("SlTO *"); TRACEPRINTF("SlTO *");
dprintkdbg(DBG_KG, dprintkdbg(DBG_KG,
"Disc: SelTO (pid=%li) for dev %02i-%i\n", "Disc: SelTO (#%li) for dev %02i-%i\n",
srb->cmd->pid, dcb->target_id, srb->cmd->pid, dcb->target_id,
dcb->target_lun); dcb->target_lun);
if (srb->retry_count++ > DC395x_MAX_RETRIES if (srb->retry_count++ > DC395x_MAX_RETRIES
...@@ -3403,7 +3357,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3403,7 +3357,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
/* /*
* SRB_DISCONNECT (This is what we expect!) * SRB_DISCONNECT (This is what we expect!)
*/ */
/* dprintkl(KERN_DEBUG, "DoWaitingSRB (pid=%li)\n", srb->cmd->pid); */ /* dprintkl(KERN_DEBUG, "DoWaitingSRB (#%li)\n", srb->cmd->pid); */
TRACEPRINTF("+*"); TRACEPRINTF("+*");
if (bval & 0x40) { if (bval & 0x40) {
dprintkdbg(DBG_0, "Debug: DISC: SCSI bus stat %02x: ACK set! Other controllers?\n", dprintkdbg(DBG_0, "Debug: DISC: SCSI bus stat %02x: ACK set! Other controllers?\n",
...@@ -3425,7 +3379,7 @@ static void disconnect(struct AdapterCtlBlk *acb) ...@@ -3425,7 +3379,7 @@ static void disconnect(struct AdapterCtlBlk *acb)
free_tag(dcb, srb); free_tag(dcb, srb);
dcb->active_srb = NULL; dcb->active_srb = NULL;
srb->state = SRB_FREE; srb->state = SRB_FREE;
/*dprintkl(KERN_DEBUG, "done (pid=%li)\n", srb->cmd->pid); */ /*dprintkl(KERN_DEBUG, "done (#%li)\n", srb->cmd->pid); */
srb_done(acb, dcb, srb); srb_done(acb, dcb, srb);
} }
} }
...@@ -3598,12 +3552,11 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) ...@@ -3598,12 +3552,11 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
if (cmd->use_sg && dir != PCI_DMA_NONE) { if (cmd->use_sg && dir != PCI_DMA_NONE) {
/* unmap DC395x SG list */ /* unmap DC395x SG list */
dprintkdbg(DBG_SGPARANOIA, dprintkdbg(DBG_SGPARANOIA,
"Unmap SG descriptor list %08x (%05x)\n", "unmap SG list %08x(%05x)\n",
srb->sg_bus_addr, srb->sg_bus_addr,
sizeof(struct SGentry) * DC395x_MAX_SG_LISTENTRY); SEGMENTX_LEN);
pci_unmap_single(acb->dev, srb->sg_bus_addr, pci_unmap_single(acb->dev, srb->sg_bus_addr,
sizeof(struct SGentry) * SEGMENTX_LEN,
DC395x_MAX_SG_LISTENTRY,
PCI_DMA_TODEVICE); PCI_DMA_TODEVICE);
dprintkdbg(DBG_SGPARANOIA, "Unmap %i SG segments from %p\n", dprintkdbg(DBG_SGPARANOIA, "Unmap %i SG segments from %p\n",
cmd->use_sg, cmd->request_buffer); cmd->use_sg, cmd->request_buffer);
...@@ -3612,7 +3565,7 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb) ...@@ -3612,7 +3565,7 @@ static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb)
(struct scatterlist *)cmd->request_buffer, (struct scatterlist *)cmd->request_buffer,
cmd->use_sg, dir); cmd->use_sg, dir);
} else if (cmd->request_buffer && dir != PCI_DMA_NONE) { } else if (cmd->request_buffer && dir != PCI_DMA_NONE) {
dprintkdbg(DBG_SGPARANOIA, "Unmap buffer at %08x (%05x)\n", dprintkdbg(DBG_SGPARANOIA, "Unmap buffer %08x(%05x)\n",
srb->segment_x[0].address, cmd->request_bufflen); srb->segment_x[0].address, cmd->request_bufflen);
pci_unmap_single(acb->dev, srb->segment_x[0].address, pci_unmap_single(acb->dev, srb->segment_x[0].address,
cmd->request_bufflen, dir); cmd->request_bufflen, dir);
...@@ -3656,17 +3609,19 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -3656,17 +3609,19 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
TRACEPRINTF("DONE *"); TRACEPRINTF("DONE *");
dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
if (cmd->use_sg) {
struct scatterlist* sg = (struct scatterlist *)cmd->request_buffer;
ptr = (struct ScsiInqData *)(page_address(sg->page) + sg->offset);
} else {
ptr = (struct ScsiInqData *)(cmd->request_buffer); ptr = (struct ScsiInqData *)(cmd->request_buffer);
if (cmd->use_sg) }
ptr =
(struct ScsiInqData *)CPU_ADDR(*(struct scatterlist *)
ptr);
dprintkdbg(DBG_SGPARANOIA, dprintkdbg(DBG_SGPARANOIA,
"SRBdone SG=%i (%i/%i), req_buf = %p, adr = %p\n", "srb_done sg=%i(%i/%i), buf=%p, addr=%p\n",
cmd->use_sg, srb->sg_index, srb->sg_count, cmd->use_sg, srb->sg_index, srb->sg_count,
cmd->request_buffer, ptr); cmd->request_buffer, ptr);
dprintkdbg(DBG_KG, dprintkdbg(DBG_KG,
"SRBdone (pid %li, target %02i-%i): ", srb->cmd->pid, "srb_done (#%li) (target %02i-%i): ", srb->cmd->pid,
srb->cmd->device->id, srb->cmd->device->lun); srb->cmd->device->id, srb->cmd->device->lun);
status = srb->target_status; status = srb->target_status;
if (srb->flag & AUTO_REQSENSE) { if (srb->flag & AUTO_REQSENSE) {
...@@ -3850,7 +3805,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -3850,7 +3805,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
else else
srb_free_insert(acb, srb); srb_free_insert(acb, srb);
dprintkdbg(DBG_0, "SRBdone: done pid %li\n", cmd->pid); dprintkdbg(DBG_0, "srb_done: done (#%li)\n", cmd->pid);
if (debug_enabled(DBG_KG)) { if (debug_enabled(DBG_KG)) {
printk(" 0x%08x\n", cmd->result); printk(" 0x%08x\n", cmd->result);
} }
...@@ -4065,9 +4020,9 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, ...@@ -4065,9 +4020,9 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
srb->segment_x[0].address = srb->segment_x[0].address =
pci_map_single(acb->dev, cmd->sense_buffer, pci_map_single(acb->dev, cmd->sense_buffer,
sizeof(cmd->sense_buffer), PCI_DMA_FROMDEVICE); sizeof(cmd->sense_buffer), PCI_DMA_FROMDEVICE);
dprintkdbg(DBG_SGPARANOIA, "Map sense buffer at %p (%05x) to %08x\n", dprintkdbg(DBG_SGPARANOIA, "Map sense buffer %p->%08x(%05x)\n",
cmd->sense_buffer, sizeof(cmd->sense_buffer), cmd->sense_buffer, srb->segment_x[0].address,
srb->segment_x[0].address); sizeof(cmd->sense_buffer));
srb->sg_count = 1; srb->sg_count = 1;
srb->sg_index = 0; srb->sg_index = 0;
...@@ -4673,8 +4628,7 @@ static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; } ...@@ -4673,8 +4628,7 @@ static int alloc_tracebufs(struct AdapterCtlBlk *acb) { return 0; }
static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
{ {
int i; int i;
const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
*sizeof(struct SGentry));
for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page) for (i = 0; i < DC395x_MAX_SRB_CNT; i += srbs_per_page)
if (acb->srb_array[i].segment_x) if (acb->srb_array[i].segment_x)
...@@ -4688,11 +4642,9 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb) ...@@ -4688,11 +4642,9 @@ static void adapter_sg_tables_free(struct AdapterCtlBlk *acb)
static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb) static int __init adapter_sg_tables_alloc(struct AdapterCtlBlk *acb)
{ {
const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1) const unsigned mem_needed = (DC395x_MAX_SRB_CNT+1)
*DC395x_MAX_SG_LISTENTRY *SEGMENTX_LEN;
*sizeof(struct SGentry);
int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE; int pages = (mem_needed+(PAGE_SIZE-1))/PAGE_SIZE;
const unsigned srbs_per_page = PAGE_SIZE/(DC395x_MAX_SG_LISTENTRY const unsigned srbs_per_page = PAGE_SIZE/SEGMENTX_LEN;
*sizeof(struct SGentry));
int srb_idx = 0; int srb_idx = 0;
unsigned i = 0; unsigned i = 0;
struct SGentry *ptr; struct SGentry *ptr;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment