Commit b48dadaa authored by Justin T. Gibbs's avatar Justin T. Gibbs

Aic7xxx Driver Update

 o Correct/Simplify ignore wide residue message handling
parent a8909fea
......@@ -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) \
......
......@@ -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 {
......
......@@ -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) {
......
......@@ -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);
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_inb(ahc, SHADDR + 3) << 24)
| (ahc_inb(ahc, SHADDR + 2) << 16)
| (ahc_inb(ahc, SHADDR + 1) << 8)
| (ahc_inb(ahc, SHADDR));
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);
}
}
}
......
......@@ -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.
*/
......
/*
* Adaptec AIC7xxx device driver for Linux.
*
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#230 $
* $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#231 $
*
* Copyright (c) 1994 John Aycock
* The University of Calgary Department of Computer Science.
......@@ -3756,7 +3756,7 @@ ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
cur_seg = (struct scatterlist *)cmd->request_buffer;
nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
scsi_to_pci_dma_dir(cmd ->sc_data_direction));
scsi_to_pci_dma_dir(cmd->sc_data_direction));
end_seg = cur_seg + nseg;
/* Copy the segments into the SG list. */
sg = scb->sg_list;
......@@ -4889,7 +4889,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
disconnected = FALSE;
else if (flag != SCB_ABORT
&& ahc_inb(ahc, SAVED_SCSIID) == pending_scb->hscb->scsiid
&& ahc_inb(ahc, SAVED_LUN) == pending_scb->hscb->lun)
&& ahc_inb(ahc, SAVED_LUN) == SCB_GET_LUN(pending_scb))
disconnected = FALSE;
}
......
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