Properly compute xs->resid, instead of assuming it'll always be 0 when
a command is done.
This commit is contained in:
parent
e88c851d08
commit
76fa396c1d
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: esiop.c,v 1.27 2004/03/16 19:10:43 bouyer Exp $ */
|
||||
/* $NetBSD: esiop.c,v 1.28 2004/05/17 11:10:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Manuel Bouyer.
|
||||
@ -33,7 +33,7 @@
|
||||
/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.27 2004/03/16 19:10:43 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.28 2004/05/17 11:10:24 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -627,7 +627,13 @@ none:
|
||||
* and the command should terminate.
|
||||
*/
|
||||
INCSTAT(esiop_stat_intr_shortxfer);
|
||||
if ((dstat & DSTAT_DFE) == 0)
|
||||
/*
|
||||
* sdp not needed here, but this
|
||||
* will cause xs->resid to be adjusted
|
||||
*/
|
||||
if (scratchc0 & A_f_c_data)
|
||||
siop_sdp(&esiop_cmd->cmd_c);
|
||||
else if ((dstat & DSTAT_DFE) == 0)
|
||||
siop_clearfifo(&sc->sc_c);
|
||||
/* no table to flush here */
|
||||
CALL_SCRIPT(Ent_status);
|
||||
@ -709,7 +715,7 @@ none:
|
||||
esiop_cmd->cmd_c.status = CMDST_DONE;
|
||||
xs->error = XS_SELTIMEOUT;
|
||||
freetarget = 1;
|
||||
goto end;
|
||||
goto end_nodata;
|
||||
} else {
|
||||
printf("%s: selection timeout without "
|
||||
"command, target %d (sdid 0x%x), "
|
||||
@ -728,7 +734,7 @@ none:
|
||||
if (esiop_cmd) {
|
||||
esiop_cmd->cmd_tables->status =
|
||||
htole32(SCSI_CHECK);
|
||||
goto end;
|
||||
goto end_nodata;
|
||||
}
|
||||
printf("%s: unexpected disconnect without "
|
||||
"command\n", sc->sc_c.sc_dev.dv_xname);
|
||||
@ -766,7 +772,7 @@ none:
|
||||
if (esiop_cmd) {
|
||||
esiop_cmd->cmd_c.status = CMDST_DONE;
|
||||
xs->error = XS_SELTIMEOUT;
|
||||
goto end;
|
||||
goto end_nodata;
|
||||
}
|
||||
need_reset = 1;
|
||||
}
|
||||
@ -811,7 +817,7 @@ scintr:
|
||||
sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
|
||||
if (xs) {
|
||||
xs->error = XS_SELTIMEOUT;
|
||||
goto end;
|
||||
goto end_nodata;
|
||||
} else {
|
||||
goto reset;
|
||||
}
|
||||
@ -1050,6 +1056,15 @@ scintr:
|
||||
* Don't call memmove in this case.
|
||||
*/
|
||||
if (offset < SIOP_NSG) {
|
||||
int i;
|
||||
/*
|
||||
* adjust xs->resid for already-transfered
|
||||
* data
|
||||
*/
|
||||
for (i = 0; i < offset; i++)
|
||||
xs->resid -= le32toh(
|
||||
esiop_cmd->cmd_tables->data[i].count
|
||||
);
|
||||
memmove(&esiop_cmd->cmd_tables->data[0],
|
||||
&esiop_cmd->cmd_tables->data[offset],
|
||||
(SIOP_NSG - offset) * sizeof(scr_table_t));
|
||||
@ -1083,7 +1098,7 @@ scintr:
|
||||
printf("unknown irqcode %x\n", irqcode);
|
||||
if (xs) {
|
||||
xs->error = XS_SELTIMEOUT;
|
||||
goto end;
|
||||
goto end_nodata;
|
||||
}
|
||||
goto reset;
|
||||
}
|
||||
@ -1092,6 +1107,12 @@ scintr:
|
||||
/* We just should't get there */
|
||||
panic("siop_intr: I shouldn't be there !");
|
||||
|
||||
end_nodata:
|
||||
/*
|
||||
* no data was transfered, and the script didn't update tlp with the
|
||||
* current offset (which is still 0)
|
||||
*/
|
||||
((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq = 0;
|
||||
end:
|
||||
/*
|
||||
* restart the script now if command completed properly
|
||||
@ -1119,6 +1140,21 @@ esiop_scsicmd_end(esiop_cmd)
|
||||
{
|
||||
struct scsipi_xfer *xs = esiop_cmd->cmd_c.xs;
|
||||
struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
|
||||
int offset, i;
|
||||
|
||||
/* scratcha was saved in tlq by script. fetch offset from it */
|
||||
offset =
|
||||
(le32toh(((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq) >> 8)
|
||||
& 0xff;
|
||||
/*
|
||||
* update resid. If we completed a xfer with
|
||||
* some data transfers, offset will be at last 1.
|
||||
* If it's 0 then either no data was transfered at
|
||||
* all, or resid was already adjusted by a save
|
||||
* data pointer, or a phase mismatch.
|
||||
*/
|
||||
for (i = 0; i < offset; i++)
|
||||
xs->resid -= le32toh(esiop_cmd->cmd_tables->data[i].count);
|
||||
|
||||
switch(xs->status) {
|
||||
case SCSI_OK:
|
||||
@ -1173,7 +1209,6 @@ esiop_scsicmd_end(esiop_cmd)
|
||||
callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
|
||||
esiop_cmd->cmd_c.status = CMDST_FREE;
|
||||
TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next);
|
||||
xs->resid = 0;
|
||||
scsipi_done (xs);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: esiopvar.h,v 1.8 2003/11/02 11:07:45 wiz Exp $ */
|
||||
/* $NetBSD: esiopvar.h,v 1.9 2004/05/17 11:10:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Manuel Bouyer.
|
||||
@ -53,6 +53,7 @@ struct esiop_slot {
|
||||
struct esiop_xfer {
|
||||
struct siop_common_xfer siop_tables;
|
||||
u_int32_t tlq; /* target/lun/tag loaded in scratchC by script */
|
||||
/* will also containt scratcha at end of command */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $ */
|
||||
/* $NetBSD: siop.c,v 1.73 2004/05/17 11:10:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000 Manuel Bouyer.
|
||||
@ -33,7 +33,7 @@
|
||||
/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.72 2004/03/16 19:10:43 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: siop.c,v 1.73 2004/05/17 11:10:24 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -494,7 +494,13 @@ siop_intr(v)
|
||||
* and the command should terminate.
|
||||
*/
|
||||
INCSTAT(siop_stat_intr_shortxfer);
|
||||
if ((dstat & DSTAT_DFE) == 0)
|
||||
/*
|
||||
* sdp not needed here, but this
|
||||
* will cause xs->resid to be adjusted
|
||||
*/
|
||||
if (scratcha0 & A_flag_data)
|
||||
siop_sdp(&siop_cmd->cmd_c);
|
||||
else if ((dstat & DSTAT_DFE) == 0)
|
||||
siop_clearfifo(&sc->sc_c);
|
||||
/* no table to flush here */
|
||||
CALL_SCRIPT(Ent_status);
|
||||
@ -889,6 +895,15 @@ scintr:
|
||||
* Don't call memmove in this case.
|
||||
*/
|
||||
if (offset < SIOP_NSG) {
|
||||
int i;
|
||||
/*
|
||||
* adjust xs->resid for already-transfered
|
||||
* data
|
||||
*/
|
||||
for (i = 0; i < offset; i++)
|
||||
xs->resid -= le32toh(
|
||||
siop_cmd->cmd_tables->data[i].count
|
||||
);
|
||||
memmove(&siop_cmd->cmd_tables->data[0],
|
||||
&siop_cmd->cmd_tables->data[offset],
|
||||
(SIOP_NSG - offset) * sizeof(scr_table_t));
|
||||
@ -918,6 +933,22 @@ scintr:
|
||||
le32toh(siop_cmd->cmd_tables->status));
|
||||
#endif
|
||||
INCSTAT(siop_stat_intr_done);
|
||||
/*
|
||||
* update resid. If we completed a xfer with
|
||||
* some data transfers, offset will be at last 1.
|
||||
* If it's 0 then either no data was transfered at
|
||||
* all, or resid was already adjusted by a save
|
||||
* data pointer, or a phase mismatch.
|
||||
*/
|
||||
offset = bus_space_read_1(sc->sc_c.sc_rt,
|
||||
sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < offset; i++)
|
||||
xs->resid -= le32toh(
|
||||
siop_cmd->cmd_tables->data[i].count
|
||||
);
|
||||
}
|
||||
siop_cmd->cmd_c.status = CMDST_DONE;
|
||||
goto end;
|
||||
default:
|
||||
@ -1017,7 +1048,6 @@ siop_scsicmd_end(siop_cmd)
|
||||
callout_stop(&siop_cmd->cmd_c.xs->xs_callout);
|
||||
siop_cmd->cmd_c.status = CMDST_FREE;
|
||||
TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
|
||||
xs->resid = 0;
|
||||
scsipi_done (xs);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: siop_common.c,v 1.33 2004/03/10 22:02:53 bouyer Exp $ */
|
||||
/* $NetBSD: siop_common.c,v 1.34 2004/05/17 11:10:24 bouyer Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000, 2002 Manuel Bouyer.
|
||||
@ -33,7 +33,7 @@
|
||||
/* SYM53c7/8xx PCI-SCSI I/O Processors driver */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: siop_common.c,v 1.33 2004/03/10 22:02:53 bouyer Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: siop_common.c,v 1.34 2004/05/17 11:10:24 bouyer Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -735,7 +735,10 @@ void
|
||||
siop_sdp(siop_cmd)
|
||||
struct siop_common_cmd *siop_cmd;
|
||||
{
|
||||
/* save data pointer. Handle async only for now */
|
||||
/*
|
||||
* Save data pointer when a phase mistmatch occurs. We need to compute
|
||||
* how much of the current table was written.
|
||||
*/
|
||||
int offset, dbc, sstat;
|
||||
struct siop_common_softc *sc = siop_cmd->siop_sc;
|
||||
scr_table_t *table; /* table to patch */
|
||||
@ -790,6 +793,9 @@ siop_sdp(siop_cmd)
|
||||
bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_CTEST3) |
|
||||
CTEST3_CLF);
|
||||
}
|
||||
/* correct xs->resid for this partial transfer */
|
||||
siop_cmd->xs->resid -= le32toh(table->count) - dbc;
|
||||
/* "cut" already transfered data from this table */
|
||||
table->addr =
|
||||
htole32(le32toh(table->addr) + le32toh(table->count) - dbc);
|
||||
table->count = htole32(dbc);
|
||||
|
@ -1,4 +1,4 @@
|
||||
; $NetBSD: esiop.ss,v 1.16 2003/10/05 17:48:49 bouyer Exp $
|
||||
; $NetBSD: esiop.ss,v 1.17 2004/05/17 11:10:24 bouyer Exp $
|
||||
|
||||
;
|
||||
; Copyright (c) 2002 Manuel Bouyer.
|
||||
@ -208,6 +208,7 @@ waitphase:
|
||||
|
||||
handle_cmpl:
|
||||
CALL REL(disconnect);
|
||||
STORE NOFLUSH SCRATCHA0, 4, from tlq_offset; save current offset
|
||||
MOVE SCRATCHE1 to SFBR;
|
||||
INT int_done, IF NOT 0x00; if status is not "done", let host handle it
|
||||
MOVE SCRATCHF0 to SFBR; load pointer in done ring
|
||||
|
Loading…
x
Reference in New Issue
Block a user