Correct/Simplify ignore wide residue message handling

aic7xxx.c:
	In ahc_handle_ign_wide_residue():
	o Use SCB_XFERLEN_ODD SCB field to determine transfer
	  "oddness" rather than the DATA_COUNT_ODD logic.
	  SCB_XFERLEN_ODD is toggled on every ignore wide
	  residue message so that multiple ignore wide residue
	  messages for the same transaction are properly supported.
	o If the sg list has been exausted, the sequencer
	  doesn't bother to update the residual data count
	  since it is known to be zero.  Perform the zeroing
	  manually before calculating the remaining data count.
	o Ensure that SG_LIST_NULL is cleared in the
	  residual sg pointer for "mid-transfer" ignore
	  wide residue cases.
	o Use multibyte in/out macros instead of shifting/masking
	  by hand.

aic7xxx.h:
	Modify the SCB_GET_LUN() macro to mask the lun hardware
	SCB field with LID.  This leaves two bits in the LUN
	field that can be used for other purposes.

aic7xxx.reg:
	Change LID to be 0x3F.  This is the maximum supported
	lun size for non-packetized SCSI.  Map the top bit
	of the lun to SCB_XFERLEN_ODD.  The host must set
	this bit whenever a transfer is an odd length.

	Remove the ODD_SEG bit field that was used to carry the odd
	transfer length information through the SG cache.  This
	is obviated by SCB_XFERLEN_ODD field.

	Remove the DATA_COUNT_ODD scratch ram byte that was used
	dynamicaly compute data transfer oddness.  This is obviated
	by SCB_XFERLEN_ODD field.

aic7xxx.seq:
	Be more careful in our handling of the SCB_LUN field.  It
	must be masked with LID if only lun information is desired.

	Remove all updates to the DATA_COUNT_ODD scratch ram field.
	Remove all uses of ODD_SEG.  These two save quite a few
	sequencer instructions.

	Use SCB_XFERLEN_ODD to validate the end of transfer
	ignore wide residue message case.

aic7xxx_inline.h:
	In ahc_queue_scb(), setup the SCB_XFERLEN_ODD field.

Approved by: RE
This commit is contained in:
Justin T. Gibbs 2003-05-26 21:24:01 +00:00
parent e4e6e6d6ea
commit 92931c12ff
5 changed files with 51 additions and 65 deletions

View File

@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#129 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#130 $
*
* $FreeBSD$
*/
@ -3573,7 +3573,7 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
sgptr = ahc_inb(ahc, SCB_RESIDUAL_SGPTR);
if ((sgptr & SG_LIST_NULL) != 0
&& ahc_inb(ahc, DATA_COUNT_ODD) == 1) {
&& (ahc_inb(ahc, SCB_LUN) & SCB_XFERLEN_ODD) != 0) {
/*
* If the residual occurred on the last
* transfer and the transfer request was
@ -3586,25 +3586,27 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
uint32_t data_addr;
uint32_t sglen;
/* Pull in the rest of the sgptr */
sgptr |= (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24)
| (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16)
| (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8);
sgptr &= SG_PTR_MASK;
data_cnt = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+3) << 24)
| (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+2) << 16)
| (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+1) << 8)
| (ahc_inb(ahc, SCB_RESIDUAL_DATACNT));
/* Pull in all of the sgptr */
sgptr = ahc_inl(ahc, SCB_RESIDUAL_SGPTR);
data_cnt = ahc_inl(ahc, SCB_RESIDUAL_DATACNT);
data_addr = (ahc_inb(ahc, SHADDR + 3) << 24)
| (ahc_inb(ahc, SHADDR + 2) << 16)
| (ahc_inb(ahc, SHADDR + 1) << 8)
| (ahc_inb(ahc, SHADDR));
if ((sgptr & SG_LIST_NULL) != 0) {
/*
* The residual data count is not updated
* for the command run to completion case.
* Explicitly zero the count.
*/
data_cnt &= ~AHC_SG_LEN_MASK;
}
data_addr = ahc_inl(ahc, SHADDR);
data_cnt += 1;
data_addr -= 1;
sgptr &= SG_PTR_MASK;
sg = ahc_sg_bus_to_virt(scb, sgptr);
/*
* The residual sg ptr points to the next S/G
* to load so we must go back one.
@ -3630,19 +3632,17 @@ ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
*/
sg++;
sgptr = ahc_sg_virt_to_bus(scb, sg);
ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 3,
sgptr >> 24);
ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 2,
sgptr >> 16);
ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 1,
sgptr >> 8);
ahc_outb(ahc, SCB_RESIDUAL_SGPTR, sgptr);
}
ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 3, data_cnt >> 24);
ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 2, data_cnt >> 16);
ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 1, data_cnt >> 8);
ahc_outb(ahc, SCB_RESIDUAL_DATACNT, data_cnt);
ahc_outl(ahc, SCB_RESIDUAL_SGPTR, sgptr);
ahc_outl(ahc, SCB_RESIDUAL_DATACNT, data_cnt);
/*
* Toggle the "oddness" of the transfer length
* to handle this mid-transfer ignore wide
* residue. This ensures that the oddness is
* correct for subsequent data transfers.
*/
ahc_outb(ahc, SCB_LUN,
ahc_inb(ahc, SCB_LUN) ^ SCB_XFERLEN_ODD);
}
}
}

View File

@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#76 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#77 $
*
* $FreeBSD$
*/
@ -93,7 +93,7 @@ struct seeprom_descriptor;
#define SCB_GET_CHANNEL(ahc, scb) \
SCSIID_CHANNEL(ahc, (scb)->hscb->scsiid)
#define SCB_GET_LUN(scb) \
((scb)->hscb->lun)
((scb)->hscb->lun & LID)
#define SCB_GET_TARGET_OFFSET(ahc, scb) \
(SCB_GET_TARGET(ahc, scb) + (SCB_IS_SCSIBUS_B(ahc, scb) ? 8 : 0))
#define SCB_GET_TARGET_MASK(ahc, scb) \

View File

@ -39,7 +39,7 @@
*
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#38 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#39 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@ -1080,7 +1080,8 @@ scb {
mask OID 0x0f
}
SCB_LUN {
mask LID 0xff
field SCB_XFERLEN_ODD 0x80
mask LID 0x3f
size 1
}
SCB_TAG {
@ -1239,7 +1240,6 @@ register SG_CACHE_PRE {
access_mode WO
address 0x0fc
mask SG_ADDR_MASK 0xf8
field ODD_SEG 0x04
field LAST_SEG 0x02
field LAST_SEG_DONE 0x01
}
@ -1248,7 +1248,6 @@ register SG_CACHE_SHADOW {
access_mode RO
address 0x0fc
mask SG_ADDR_MASK 0xf8
field ODD_SEG 0x04
field LAST_SEG 0x02
field LAST_SEG_DONE 0x01
}
@ -1478,14 +1477,6 @@ scratch_ram {
field ENAUTOATNI 0x04
field ENAUTOATNP 0x02
}
/*
* Track whether the transfer byte count for
* the current data phase is odd.
*/
DATA_COUNT_ODD {
size 1
}
}
scratch_ram {

View File

@ -40,7 +40,7 @@
* $FreeBSD$
*/
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#54 $"
VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#55 $"
PATCH_ARG_LIST = "struct ahc_softc *ahc"
PREFIX = "ahc_"
@ -437,7 +437,7 @@ select_out:
mov SCBPTR, WAITING_SCBH;
mov WAITING_SCBH,SCB_NEXT;
mov SAVED_SCSIID, SCB_SCSIID;
mov SAVED_LUN, SCB_LUN;
and SAVED_LUN, LID, SCB_LUN;
call set_transfer_settings;
if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SSTAT0, TARGET jz initiator_select;
@ -461,7 +461,7 @@ select_out:
/*
* Start out with a simple identify message.
*/
or SCB_LUN, MSG_IDENTIFYFLAG call target_outb;
or SAVED_LUN, MSG_IDENTIFYFLAG call target_outb;
/*
* If we are the result of a tagged command, send
@ -768,16 +768,12 @@ idle_sg_avail:
/* Does the hardware have space for another SG entry? */
test DFSTATUS, PRELOAD_AVAIL jz return;
bmov HADDR, CCSGRAM, 7;
test HCNT[0], 0x1 jz . + 2;
xor DATA_COUNT_ODD, 0x1;
bmov SCB_RESIDUAL_DATACNT[3], CCSGRAM, 1;
if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
mov SCB_RESIDUAL_DATACNT[3] call set_hhaddr;
}
call sg_advance;
mov SINDEX, SCB_RESIDUAL_SGPTR[0];
test DATA_COUNT_ODD, 0x1 jz . + 2;
or SINDEX, ODD_SEG;
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
or SINDEX, LAST_SEG;
mov SG_CACHE_PRE, SINDEX;
@ -875,7 +871,6 @@ data_phase_initialize:
call calc_mwi_residual;
}
and SCB_RESIDUAL_SGPTR[0], ~SG_FULL_RESID;
and DATA_COUNT_ODD, 0x1, HCNT[0];
if ((ahc->features & AHC_ULTRA2) == 0) {
if ((ahc->features & AHC_CMD_CHAN) != 0) {
@ -910,8 +905,6 @@ data_phase_inbounds:
mov SINDEX, SCB_RESIDUAL_SGPTR[0];
test SCB_RESIDUAL_DATACNT[3], SG_LAST_SEG jz . + 2;
or SINDEX, LAST_SEG;
test DATA_COUNT_ODD, 0x1 jz . + 2;
or SINDEX, ODD_SEG;
mov SG_CACHE_PRE, SINDEX;
mov DFCNTRL, DMAPARAMS;
ultra2_dma_loop:
@ -1006,10 +999,8 @@ sgptr_fixup:
adc SCB_RESIDUAL_SGPTR[3], -1;
sgptr_fixup_done:
and SCB_RESIDUAL_SGPTR[0], SG_ADDR_MASK, SG_CACHE_SHADOW;
clr DATA_COUNT_ODD;
test SG_CACHE_SHADOW, ODD_SEG jz . + 2;
or DATA_COUNT_ODD, 0x1;
clr SCB_RESIDUAL_DATACNT[3]; /* We are not the last seg */
/* We are not the last seg */
and SCB_RESIDUAL_DATACNT[3], ~SG_LAST_SEG;
residuals_correct:
/*
* Go ahead and shut down the DMA engine now.
@ -1246,9 +1237,6 @@ sg_load_done:
} else {
call set_stcnt_from_hcnt;
}
/* Track odd'ness */
test HCNT[0], 0x1 jz . + 2;
xor DATA_COUNT_ODD, 0x1;
if ((ahc->flags & AHC_TARGETROLE) != 0) {
test SSTAT0, TARGET jnz data_phase_loop;
@ -1350,7 +1338,7 @@ residual_update_done:
*/
test DFCNTRL, DIRECTION jz target_ITloop;
test SSTAT1, REQINIT jnz .;
test DATA_COUNT_ODD, 0x1 jz target_ITloop;
test SCB_LUN, SCB_XFERLEN_ODD jz target_ITloop;
test SCSIRATE, WIDEXFER jz target_ITloop;
/*
* Issue an Ignore Wide Residue Message.
@ -1510,7 +1498,7 @@ p_mesgout:
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
p_mesgout_identify:
or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SAVED_LUN;
test SCB_CONTROL, DISCENB jnz . + 2;
and SINDEX, ~DISCENB;
/*
@ -1587,7 +1575,7 @@ if ((ahc->features & AHC_WIDE) != 0) {
mvi ARG_1 call inb_next;
cmp ARG_1, 0x01 jne mesgin_reject;
test SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL jz . + 2;
test DATA_COUNT_ODD, 0x1 jz mesgin_done;
test SCB_LUN, SCB_XFERLEN_ODD jnz mesgin_done;
mvi IGN_WIDE_RES call set_seqint;
jmp mesgin_done;
}
@ -1716,7 +1704,7 @@ mesgin_disconnect:
}
test SCB_CONTROL, TAG_ENB jnz await_busfree;
mov ARG_1, SCB_TAG;
mov SAVED_LUN, SCB_LUN;
and SAVED_LUN, LID, SCB_LUN;
mov SCB_SCSIID call set_busy_target;
jmp await_busfree;
@ -1859,7 +1847,7 @@ mesgin_identify:
* at a time. So, if the lun doesn't match, look
* for a tag message.
*/
mov A, SCB_LUN;
and A, LID, SCB_LUN;
cmp SAVED_LUN, A je setup_SCB_id_lun_okay;
if ((ahc->flags & AHC_PAGESCBS) != 0) {
/*
@ -1917,7 +1905,7 @@ setup_SCB:
or SEQ_FLAGS, 0x8;
}
setup_SCB_id_okay:
mov A, SCB_LUN;
and A, LID, SCB_LUN;
cmp SAVED_LUN, A jne not_found_cleanup_scb;
setup_SCB_id_lun_okay:
if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {

View File

@ -37,7 +37,7 @@
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#42 $
* $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#43 $
*
* $FreeBSD$
*/
@ -454,6 +454,13 @@ ahc_queue_scb(struct ahc_softc *ahc, struct scb *scb)
panic("Attempt to queue invalid SCB tag %x:%x\n",
scb->hscb->tag, scb->hscb->next);
/*
* Setup data "oddness".
*/
scb->hscb->lun &= LID;
if (ahc_get_transfer_length(scb) & 0x1)
scb->hscb->lun |= SCB_XFERLEN_ODD;
/*
* Keep a history of SCBs we've downloaded in the qinfifo.
*/