summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/aic7xxx/aic7770.c7
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c406
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h56
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg11
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq21
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.c81
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h8
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c81
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c10
9 files changed, 371 insertions, 310 deletions
diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c
index c493da2..ac23d19 100644
--- a/sys/dev/aic7xxx/aic7770.c
+++ b/sys/dev/aic7xxx/aic7770.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7770.c#8 $
+ * $Id: //depot/src/aic7xxx/aic7770.c#9 $
*
* $FreeBSD$
*/
@@ -217,6 +217,11 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
*/
ahc_outb(ahc, BCTL, ENABLE);
+ /*
+ * Allow interrupts.
+ */
+ ahc_intr_enable(ahc, TRUE);
+
return (0);
}
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index c0192a5..1e5a8b3 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.c#34 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.c#35 $
*
* $FreeBSD$
*/
@@ -137,7 +137,7 @@ static struct ahc_syncrate ahc_syncrates[] =
#include "aic7xxx_seq.h"
/**************************** Function Declarations ***************************/
-static struct tmode_tstate*
+static struct ahc_tmode_tstate*
ahc_alloc_tstate(struct ahc_softc *ahc,
u_int scsi_id, char channel);
#ifdef AHC_TARGET_MODE
@@ -150,7 +150,7 @@ static struct ahc_syncrate*
u_int *period,
u_int *ppr_options,
role_t role);
-static void ahc_update_pending_syncrates(struct ahc_softc *ahc);
+static void ahc_update_pending_scbs(struct ahc_softc *ahc);
static void ahc_fetch_devinfo(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
static void ahc_scb_devinfo(struct ahc_softc *ahc,
@@ -190,6 +190,9 @@ static void ahc_handle_devreset(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
cam_status status, char *message,
int verbose_level);
+static void ahc_setup_target_msgin(struct ahc_softc *ahc,
+ struct ahc_devinfo *devinfo,
+ struct scb *scb);
static bus_dmamap_callback_t ahc_dmamap_cb;
static void ahc_build_free_scb_list(struct ahc_softc *ahc);
@@ -220,7 +223,7 @@ static void ahc_download_instr(struct ahc_softc *ahc,
u_int instrptr, uint8_t *dconsts);
#ifdef AHC_TARGET_MODE
static void ahc_queue_lstate_event(struct ahc_softc *ahc,
- struct tmode_lstate *lstate,
+ struct ahc_tmode_lstate *lstate,
u_int initiator_id,
u_int event_type,
u_int event_arg);
@@ -452,6 +455,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
break;
case SCSI_STATUS_CMD_TERMINATED:
case SCSI_STATUS_CHECK_COND:
+ {
+ struct ahc_dma_seg *sg;
+ struct scsi_sense *sc;
+ struct ahc_initiator_tinfo *targ_info;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_transinfo *tinfo;
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOWSENSE) {
ahc_print_path(ahc, scb);
@@ -460,99 +469,97 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
}
#endif
- if (ahc_perform_autosense(scb)) {
- struct ahc_dma_seg *sg;
- struct scsi_sense *sc;
- struct ahc_initiator_tinfo *targ_info;
- struct tmode_tstate *tstate;
- struct ahc_transinfo *tinfo;
+ if (ahc_perform_autosense(scb) == 0)
+ break;
- targ_info =
- ahc_fetch_transinfo(ahc,
+ targ_info = ahc_fetch_transinfo(ahc,
devinfo.channel,
devinfo.our_scsiid,
devinfo.target,
&tstate);
- tinfo = &targ_info->current;
- sg = scb->sg_list;
- sc = (struct scsi_sense *)
- (&hscb->shared_data.cdb);
- /*
- * Save off the residual if there is one.
- */
- if (ahc_check_residual(scb))
- ahc_calc_residual(scb);
- else
- ahc_set_residual(scb, 0);
+ tinfo = &targ_info->current;
+ sg = scb->sg_list;
+ sc = (struct scsi_sense *)(&hscb->shared_data.cdb);
+ /*
+ * Save off the residual if there is one.
+ */
+ if (ahc_check_residual(scb))
+ ahc_calc_residual(scb);
+ else
+ ahc_set_residual(scb, 0);
#ifdef AHC_DEBUG
- if (ahc_debug & AHC_SHOWSENSE) {
- ahc_print_path(ahc, scb);
- printf("Sending Sense\n");
- }
+ if (ahc_debug & AHC_SHOWSENSE) {
+ ahc_print_path(ahc, scb);
+ printf("Sending Sense\n");
+ }
#endif
- sg->addr = ahc_get_sense_bufaddr(ahc, scb);
- sg->len = ahc_get_sense_bufsize(ahc, scb);
- sg->len |= AHC_DMA_LAST_SEG;
-
- /* Fixup byte order */
- sg->addr = ahc_htole32(sg->addr);
- sg->len = ahc_htole32(sg->len);
-
- sc->opcode = REQUEST_SENSE;
- sc->byte2 = 0;
- if (tinfo->protocol_version <= SCSI_REV_2
- && SCB_GET_LUN(scb) < 8)
- sc->byte2 = SCB_GET_LUN(scb) << 5;
- sc->unused[0] = 0;
- sc->unused[1] = 0;
- sc->length = sg->len;
- sc->control = 0;
+ sg->addr = ahc_get_sense_bufaddr(ahc, scb);
+ sg->len = ahc_get_sense_bufsize(ahc, scb);
+ sg->len |= AHC_DMA_LAST_SEG;
+
+ /* Fixup byte order */
+ sg->addr = ahc_htole32(sg->addr);
+ sg->len = ahc_htole32(sg->len);
+
+ sc->opcode = REQUEST_SENSE;
+ sc->byte2 = 0;
+ if (tinfo->protocol_version <= SCSI_REV_2
+ && SCB_GET_LUN(scb) < 8)
+ sc->byte2 = SCB_GET_LUN(scb) << 5;
+ sc->unused[0] = 0;
+ sc->unused[1] = 0;
+ sc->length = sg->len;
+ sc->control = 0;
- /*
- * XXX Still true???
- * Would be nice to preserve DISCENB here,
- * but due to the way we manage busy targets,
- * we can't.
- */
- hscb->control = 0;
+ /*
+ * We can't allow the target to disconnect.
+ * This will be an untagged transaction and
+ * having the target disconnect will make this
+ * transaction indestinguishable from outstanding
+ * tagged transactions.
+ */
+ hscb->control = 0;
- /*
- * This request sense could be because the
- * the device lost power or in some other
- * way has lost our transfer negotiations.
- * Renegotiate if appropriate. Unit attention
- * errors will be reported before any data
- * phases occur.
- */
- if (ahc_get_residual(scb)
- == ahc_get_transfer_length(scb)) {
- ahc_update_target_msg_request(ahc,
- &devinfo,
- targ_info,
- /*force*/TRUE,
- /*paused*/TRUE);
- }
- hscb->cdb_len = sizeof(*sc);
- hscb->dataptr = sg->addr;
- hscb->datacnt = sg->len;
- hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
- hscb->sgptr = ahc_htole32(hscb->sgptr);
- scb->sg_count = 1;
- scb->flags |= SCB_SENSE;
- ahc_qinfifo_requeue_tail(ahc, scb);
- ahc_outb(ahc, RETURN_1, SEND_SENSE);
+ /*
+ * This request sense could be because the
+ * the device lost power or in some other
+ * way has lost our transfer negotiations.
+ * Renegotiate if appropriate. Unit attention
+ * errors will be reported before any data
+ * phases occur.
+ */
+ if (ahc_get_residual(scb)
+ == ahc_get_transfer_length(scb)) {
+ ahc_update_neg_request(ahc, &devinfo,
+ tstate, targ_info,
+ /*force*/TRUE);
+ }
+ if (tstate->auto_negotiate & devinfo.target_mask) {
+ hscb->control |= MK_MESSAGE;
+ scb->flags &= ~SCB_NEGOTIATE;
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ }
+ hscb->cdb_len = sizeof(*sc);
+ hscb->dataptr = sg->addr;
+ hscb->datacnt = sg->len;
+ hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
+ hscb->sgptr = ahc_htole32(hscb->sgptr);
+ scb->sg_count = 1;
+ scb->flags |= SCB_SENSE;
+ ahc_qinfifo_requeue_tail(ahc, scb);
+ ahc_outb(ahc, RETURN_1, SEND_SENSE);
#ifdef __FreeBSD__
- /*
- * Ensure we have enough time to actually
- * retrieve the sense.
- */
- untimeout(ahc_timeout, (caddr_t)scb,
- scb->io_ctx->ccb_h.timeout_ch);
- scb->io_ctx->ccb_h.timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
+ /*
+ * Ensure we have enough time to actually
+ * retrieve the sense.
+ */
+ untimeout(ahc_timeout, (caddr_t)scb,
+ scb->io_ctx->ccb_h.timeout_ch);
+ scb->io_ctx->ccb_h.timeout_ch =
+ timeout(ahc_timeout, (caddr_t)scb, 5 * hz);
#endif
- }
break;
+ }
default:
break;
}
@@ -666,6 +673,8 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* loop.
*/
if (ahc->msg_type == MSG_TYPE_NONE) {
+ struct scb *scb;
+ u_int scb_index;
u_int bus_phase;
bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
@@ -683,13 +692,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
return;
}
+ scb_index = ahc_inb(ahc, SCB_TAG);
+ scb = ahc_lookup_scb(ahc, scb_index);
if (devinfo.role == ROLE_INITIATOR) {
- struct scb *scb;
- u_int scb_index;
-
- scb_index = ahc_inb(ahc, SCB_TAG);
- scb = ahc_lookup_scb(ahc, scb_index);
-
if (scb == NULL)
panic("HOST_MSG_LOOP with "
"invalid SCB %x\n", scb_index);
@@ -711,7 +716,9 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
}
#if AHC_TARGET_MODE
else
- ahc_setup_target_msgin(ahc, &devinfo);
+ ahc_setup_target_msgin(ahc,
+ &devinfo,
+ scb);
#endif
}
}
@@ -1129,7 +1136,7 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
} else if (ahc_sent_msg(ahc, AHCMSG_EXT,
MSG_EXT_PPR, FALSE)) {
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
/*
* PPR Rejected. Try non-ppr negotiation
@@ -1380,11 +1387,11 @@ ahc_print_scb(struct scb *scb)
* Allocate per target mode instance (ID we respond to as a target)
* transfer negotiation data structures.
*/
-static struct tmode_tstate *
+static struct ahc_tmode_tstate *
ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
{
- struct tmode_tstate *master_tstate;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *master_tstate;
+ struct ahc_tmode_tstate *tstate;
int i;
master_tstate = ahc->enabled_targets[ahc->our_id];
@@ -1430,11 +1437,13 @@ ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
static void
ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
{
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
- /* Don't clean up the entry for our initiator role */
- if ((ahc->flags & AHC_INITIATORROLE) != 0
- && ((channel == 'B' && scsi_id == ahc->our_id_b)
+ /*
+ * Don't clean up our "master" tstate.
+ * It has our default user settings.
+ */
+ if (((channel == 'B' && scsi_id == ahc->our_id_b)
|| (channel == 'A' && scsi_id == ahc->our_id))
&& force == FALSE)
return;
@@ -1664,15 +1673,14 @@ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo,
* means the next time we send the initial identify messages for
* a new transaction.
*/
-void
-ahc_update_target_msg_request(struct ahc_softc *ahc,
- struct ahc_devinfo *devinfo,
- struct ahc_initiator_tinfo *tinfo,
- int force, int paused)
+int
+ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+ struct ahc_tmode_tstate *tstate,
+ struct ahc_initiator_tinfo *tinfo, int force)
{
- u_int targ_msg_req_orig;
+ u_int auto_negotiate_orig;
- targ_msg_req_orig = ahc->targ_msg_req;
+ auto_negotiate_orig = tstate->auto_negotiate;
if (tinfo->current.period != tinfo->goal.period
|| tinfo->current.width != tinfo->goal.width
|| tinfo->current.offset != tinfo->goal.offset
@@ -1681,23 +1689,11 @@ ahc_update_target_msg_request(struct ahc_softc *ahc,
&& (tinfo->goal.period != 0
|| tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
|| tinfo->goal.ppr_options != 0)))
- ahc->targ_msg_req |= devinfo->target_mask;
+ tstate->auto_negotiate |= devinfo->target_mask;
else
- ahc->targ_msg_req &= ~devinfo->target_mask;
+ tstate->auto_negotiate &= ~devinfo->target_mask;
- if (ahc->targ_msg_req != targ_msg_req_orig) {
- /* Update the message request bit for this target */
- if (!paused)
- ahc_pause(ahc);
-
- ahc_outb(ahc, TARGET_MSG_REQUEST,
- ahc->targ_msg_req & 0xFF);
- ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
- (ahc->targ_msg_req >> 8) & 0xFF);
-
- if (!paused)
- ahc_unpause(ahc);
- }
+ return (auto_negotiate_orig != tstate->auto_negotiate);
}
/*
@@ -1714,11 +1710,15 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
u_int offset, u_int ppr_options, u_int type, int paused)
{
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
u_int old_period;
u_int old_offset;
u_int old_ppr;
- int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+ int active;
+ int update_needed;
+
+ active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+ update_needed = 0;
if (syncrate == NULL) {
period = 0;
@@ -1750,6 +1750,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
|| old_ppr != ppr_options)) {
u_int scsirate;
+ update_needed++;
scsirate = tinfo->scsirate;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1798,9 +1799,6 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
tinfo->current.offset = offset;
tinfo->current.ppr_options = ppr_options;
- /* Update the syncrates in any pending scbs */
- ahc_update_pending_syncrates(ahc);
-
ahc_send_async(ahc, devinfo->channel, devinfo->target,
CAM_LUN_WILDCARD, AC_TRANSFER_NEG);
if (bootverbose) {
@@ -1818,9 +1816,11 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
}
- ahc_update_target_msg_request(ahc, devinfo, tinfo,
- /*force*/FALSE,
- paused);
+ update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+ tinfo, /*force*/FALSE);
+
+ if (update_needed)
+ ahc_update_pending_scbs(ahc);
}
/*
@@ -1835,11 +1835,14 @@ void
ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
u_int width, u_int type, int paused)
{
- struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
- u_int oldwidth;
- int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+ struct ahc_initiator_tinfo *tinfo;
+ struct ahc_tmode_tstate *tstate;
+ u_int oldwidth;
+ int active;
+ int update_needed;
+ active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
+ update_needed = 0;
tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
devinfo->target, &tstate);
@@ -1853,6 +1856,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
u_int scsirate;
+ update_needed++;
scsirate = tinfo->scsirate;
scsirate &= ~WIDEXFER;
if (width == MSG_EXT_WDTR_BUS_16_BIT)
@@ -1874,8 +1878,10 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
}
- ahc_update_target_msg_request(ahc, devinfo, tinfo,
- /*force*/FALSE, paused);
+ update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
+ tinfo, /*force*/FALSE);
+ if (update_needed)
+ ahc_update_pending_scbs(ahc);
}
/*
@@ -1885,7 +1891,7 @@ void
ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
{
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
uint16_t orig_tagenable;
tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
@@ -1911,7 +1917,7 @@ ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
* be set correctly during future (re)selections.
*/
static void
-ahc_update_pending_syncrates(struct ahc_softc *ahc)
+ahc_update_pending_scbs(struct ahc_softc *ahc)
{
struct scb *pending_scb;
int pending_scb_count;
@@ -1927,7 +1933,7 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc)
struct ahc_devinfo devinfo;
struct hardware_scb *pending_hscb;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
ahc_scb_devinfo(ahc, &devinfo, pending_scb);
tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
@@ -1939,6 +1945,11 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc)
pending_hscb->control |= ULTRAENB;
pending_hscb->scsirate = tinfo->scsirate;
pending_hscb->scsioffset = tinfo->current.offset;
+ if ((tstate->auto_negotiate & devinfo.target_mask) == 0
+ && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
+ pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
+ pending_hscb->control &= ~MK_MESSAGE;
+ }
pending_scb_count++;
}
@@ -1960,9 +1971,8 @@ ahc_update_pending_syncrates(struct ahc_softc *ahc)
pending_hscb = pending_scb->hscb;
control = ahc_inb(ahc, SCB_CONTROL);
- control &= ~ULTRAENB;
- if ((pending_hscb->control & ULTRAENB) != 0)
- control |= ULTRAENB;
+ control &= ~(ULTRAENB|MK_MESSAGE);
+ control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE);
ahc_outb(ahc, SCB_CONTROL, control);
ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate);
ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset);
@@ -2118,8 +2128,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
* away.
*/
ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
- } else if ((ahc->targ_msg_req & devinfo->target_mask) != 0
- || (scb->flags & SCB_NEGOTIATE) != 0) {
+ } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
ahc_build_transfer_msg(ahc, devinfo);
} else {
printf("ahc_intr: AWAITING_MSG for an SCB that "
@@ -2136,6 +2145,7 @@ ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
* asked to send this message again.
*/
ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE);
+ scb->hscb->control &= ~MK_MESSAGE;
ahc->msgout_index = 0;
ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
}
@@ -2153,7 +2163,7 @@ ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
* we want to renegotiate due to a check condition.
*/
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
struct ahc_syncrate *rate;
int dowide;
int dosync;
@@ -2610,7 +2620,7 @@ static int
ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
{
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
int reject;
int done;
int response;
@@ -2709,7 +2719,8 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
/*
* Send our own SDTR in reply
*/
- if (bootverbose) {
+ if (bootverbose
+ && devinfo->role == ROLE_INITIATOR) {
printf("(%s:%c:%d:%d): Target "
"Initiated SDTR\n",
ahc_name(ahc), devinfo->channel,
@@ -2779,7 +2790,8 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
/*
* Send our own WDTR in reply
*/
- if (bootverbose) {
+ if (bootverbose
+ && devinfo->role == ROLE_INITIATOR) {
printf("(%s:%c:%d:%d): Target "
"Initiated WDTR\n",
ahc_name(ahc), devinfo->channel,
@@ -2962,7 +2974,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
tstate = ahc->enabled_targets[devinfo->our_scsiid];
if (tstate != NULL) {
- struct tmode_lstate* lstate;
+ struct ahc_tmode_lstate* lstate;
lstate = tstate->enabled_luns[devinfo->lun];
if (lstate != NULL) {
@@ -3014,7 +3026,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
*/
struct scb *scb;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
u_int scb_index;
u_int last_msg;
int response = 0;
@@ -3260,7 +3272,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
cam_status status, char *message, int verbose_level)
{
#ifdef AHC_TARGET_MODE
- struct tmode_tstate* tstate;
+ struct ahc_tmode_tstate* tstate;
u_int lun;
#endif
int found;
@@ -3277,7 +3289,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
tstate = ahc->enabled_targets[devinfo->our_scsiid];
if (tstate != NULL) {
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
- struct tmode_lstate* lstate;
+ struct ahc_tmode_lstate* lstate;
lstate = tstate->enabled_luns[lun];
if (lstate == NULL)
@@ -3309,9 +3321,11 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
#ifdef AHC_TARGET_MODE
-void
-ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
+static void
+ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
+ struct scb *scb)
{
+
/*
* To facilitate adding multiple messages together,
* each routine should increment the index and len
@@ -3320,7 +3334,7 @@ ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
ahc->msgout_index = 0;
ahc->msgout_len = 0;
- if ((ahc->targ_msg_req & devinfo->target_mask) != 0)
+ if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
ahc_build_transfer_msg(ahc, devinfo);
else
panic("ahc_intr: AWAITING target message with no message");
@@ -3354,6 +3368,7 @@ ahc_alloc(void *platform_arg, char *name)
LIST_INIT(&ahc->pending_scbs);
/* We don't know our unit number until the OSM sets it */
ahc->name = name;
+ ahc->unit = -1;
for (i = 0; i < 16; i++)
TAILQ_INIT(&ahc->untagged_queues[i]);
if (ahc_platform_alloc(ahc, platform_arg) != 0) {
@@ -3372,7 +3387,7 @@ ahc_softc_init(struct ahc_softc *ahc, struct ahc_probe_config *config)
ahc->bugs = config->bugs;
ahc->flags = config->flags;
ahc->channel = config->channel;
- ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
+ ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS);
ahc->description = config->description;
/* The IRQMS bit is only valid on VL and EISA chips */
if ((ahc->chip & AHC_PCI) != 0)
@@ -3498,7 +3513,7 @@ ahc_free(struct ahc_softc *ahc)
#endif
ahc_platform_free(ahc);
for (i = 0; i < AHC_NUM_TARGETS; i++) {
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
tstate = ahc->enabled_targets[i];
if (tstate != NULL) {
@@ -3506,7 +3521,7 @@ ahc_free(struct ahc_softc *ahc)
int j;
for (j = 0; j < AHC_NUM_LUNS; j++) {
- struct tmode_lstate *lstate;
+ struct ahc_tmode_lstate *lstate;
lstate = tstate->enabled_luns[j];
if (lstate != NULL) {
@@ -4167,16 +4182,16 @@ ahc_init(struct ahc_softc *ahc)
* data for any target mode initiator.
*/
if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) {
- printf("%s: unable to allocate tmode_tstate. "
+ printf("%s: unable to allocate ahc_tmode_tstate. "
"Failing attach\n", ahc_name(ahc));
- return (-1);
+ return (ENOMEM);
}
if ((ahc->features & AHC_TWIN) != 0) {
if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) {
- printf("%s: unable to allocate tmode_tstate. "
+ printf("%s: unable to allocate ahc_tmode_tstate. "
"Failing attach\n", ahc_name(ahc));
- return (-1);
+ return (ENOMEM);
}
}
@@ -4274,7 +4289,7 @@ ahc_init(struct ahc_softc *ahc)
for (i = 0; i <= max_targ; i++) {
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
u_int our_id;
u_int target_id;
char channel;
@@ -4438,10 +4453,6 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, QINPOS, 0);
ahc_outb(ahc, QOUTPOS, 0);
- /* Don't have any special messages to send to targets */
- ahc_outb(ahc, TARGET_MSG_REQUEST, 0);
- ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0);
-
/*
* Use the built in queue management registers
* if they are available.
@@ -4503,6 +4514,23 @@ ahc_init(struct ahc_softc *ahc)
return (0);
}
+void
+ahc_intr_enable(struct ahc_softc *ahc, int enable)
+{
+ u_int hcntrl;
+
+ hcntrl = ahc_inb(ahc, HCNTRL);
+ hcntrl &= ~INTEN;
+ ahc->pause &= ~INTEN;
+ ahc->unpause &= ~INTEN;
+ if (enable) {
+ hcntrl |= INTEN;
+ ahc->pause |= INTEN;
+ ahc->unpause |= INTEN;
+ }
+ ahc_outb(ahc, HCNTRL, hcntrl);
+}
+
/*
* Ensure that the card is paused in a location
* outside of all critical sections and that all
@@ -5521,14 +5549,14 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
* drivers affected by this action.
*/
for (target = 0; target <= max_scsiid; target++) {
- struct tmode_tstate* tstate;
+ struct ahc_tmode_tstate* tstate;
u_int lun;
tstate = ahc->enabled_targets[target];
if (tstate == NULL)
continue;
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
- struct tmode_lstate* lstate;
+ struct ahc_tmode_lstate* lstate;
lstate = tstate->enabled_luns[lun];
if (lstate == NULL)
@@ -5666,7 +5694,7 @@ ahc_calc_residual(struct scb *scb)
* Add a target mode event to this lun's queue
*/
static void
-ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate,
+ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate,
u_int initiator_id, u_int event_type, u_int event_arg)
{
struct ahc_tmode_event *event;
@@ -5717,7 +5745,7 @@ ahc_queue_lstate_event(struct ahc_softc *ahc, struct tmode_lstate *lstate,
* for immediate notify resources.
*/
void
-ahc_send_lstate_events(struct ahc_softc *ahc, struct tmode_lstate *lstate)
+ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate)
{
struct ccb_hdr *ccbh;
struct ccb_immed_notify *inot;
@@ -6043,6 +6071,7 @@ ahc_dump_card_state(struct ahc_softc *ahc)
int target;
int maxtarget;
int i;
+ uint8_t last_phase;
uint8_t qinpos;
uint8_t qintail;
uint8_t qoutpos;
@@ -6051,13 +6080,25 @@ ahc_dump_card_state(struct ahc_softc *ahc)
saved_scbptr = ahc_inb(ahc, SCBPTR);
- printf("%s: Dumping Card State at SEQADDR 0x%x\n",
- ahc_name(ahc),
+ last_phase = ahc_inb(ahc, LASTPHASE);
+ printf("%s: Dumping Card State %s, at SEQADDR 0x%x\n",
+ ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg,
ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
-
- printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x, SSTAT0 0x%x\n",
- ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL),
- ahc_inb(ahc, SSTAT0));
+ printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n",
+ ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL));
+ printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n",
+ ahc_inb(ahc, DFCNTRL), ahc_inb(ahc, DFSTATUS));
+ printf("LASTPHASE = 0x%x, SCSISIGI = 0x%x, SXFRCTL0 = 0x%x\n",
+ last_phase, ahc_inb(ahc, SCSISIGI), ahc_inb(ahc, SXFRCTL0));
+ printf("SSTAT0 = 0x%x, SSTAT1 = 0x%x\n",
+ ahc_inb(ahc, SSTAT0), ahc_inb(ahc, SSTAT1));
+ if ((ahc->features & AHC_DT) != 0)
+ printf("SCSIPHASE = 0x%x\n", ahc_inb(ahc, SCSIPHASE));
+ printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n",
+ ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+ ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+ ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
+ ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8));
printf("SCB count = %d\n", ahc->scb_data->numscbs);
printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag);
printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB));
@@ -6155,7 +6196,8 @@ ahc_dump_card_state(struct ahc_softc *ahc)
#ifdef AHC_TARGET_MODE
cam_status
ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
- struct tmode_tstate **tstate, struct tmode_lstate **lstate,
+ struct ahc_tmode_tstate **tstate,
+ struct ahc_tmode_lstate **lstate,
int notfound_failure)
{
@@ -6196,8 +6238,8 @@ ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
void
ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
struct ccb_en_lun *cel;
cam_status status;
u_int target;
@@ -6605,8 +6647,8 @@ ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
static int
ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
struct ccb_accept_tio *atio;
uint8_t *byte;
int initiator;
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index 329a58d..eada9ad 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.h#22 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.h#24 $
*
* $FreeBSD$
*/
@@ -515,8 +515,9 @@ typedef enum {
SCB_DEVICE_RESET = 0x0004,
SCB_SENSE = 0x0008,
SCB_CDB32_PTR = 0x0010,
- SCB_RECOVERY_SCB = 0x0040,
- SCB_NEGOTIATE = 0x0080,
+ SCB_RECOVERY_SCB = 0x0020,
+ SCB_AUTO_NEGOTIATE = 0x0040,/* Negotiate to achieve goal. */
+ SCB_NEGOTIATE = 0x0080,/* Negotiation forced for command. */
SCB_ABORT = 0x1000,
SCB_UNTAGGEDQ = 0x2000,
SCB_ACTIVE = 0x4000,
@@ -625,7 +626,7 @@ struct ahc_tmode_event {
* data structures.
*/
#ifdef AHC_TARGET_MODE
-struct tmode_lstate {
+struct ahc_tmode_lstate {
struct cam_path *path;
struct ccb_hdr_slist accept_tios;
struct ccb_hdr_slist immed_notifies;
@@ -634,7 +635,7 @@ struct tmode_lstate {
uint8_t event_w_idx;
};
#else
-struct tmode_lstate;
+struct ahc_tmode_lstate;
#endif
/******************** Transfer Negotiation Datastructures *********************/
@@ -671,16 +672,17 @@ struct ahc_initiator_tinfo {
* that we are the target and the targets are the initiators since the
* negotiation is the same regardless of role.
*/
-struct tmode_tstate {
- struct tmode_lstate* enabled_luns[AHC_NUM_LUNS];
+struct ahc_tmode_tstate {
+ struct ahc_tmode_lstate* enabled_luns[AHC_NUM_LUNS];
struct ahc_initiator_tinfo transinfo[AHC_NUM_TARGETS];
/*
* Per initiator state bitmasks.
*/
- uint16_t ultraenb; /* Using ultra sync rate */
- uint16_t discenable; /* Disconnection allowed */
- uint16_t tagenable; /* Tagged Queuing allowed */
+ uint16_t auto_negotiate;/* Auto Negotiation Required */
+ uint16_t ultraenb; /* Using ultra sync rate */
+ uint16_t discenable; /* Disconnection allowed */
+ uint16_t tagenable; /* Tagged Queuing allowed */
};
/*
@@ -841,6 +843,8 @@ struct ahc_suspend_state {
uint8_t *btt;
};
+typedef void (*ahc_bus_intr_t)(struct ahc_softc *);
+
struct ahc_softc {
bus_space_tag_t tag;
bus_space_handle_t bsh;
@@ -884,24 +888,29 @@ struct ahc_softc {
ahc_dev_softc_t dev_softc;
/*
+ * Bus specific device information.
+ */
+ ahc_bus_intr_t bus_intr;
+
+ /*
* Target mode related state kept on a per enabled lun basis.
* Targets that are not enabled will have null entries.
* As an initiator, we keep one target entry for our initiator
* ID to store our sync/wide transfer settings.
*/
- struct tmode_tstate* enabled_targets[AHC_NUM_TARGETS];
+ struct ahc_tmode_tstate *enabled_targets[AHC_NUM_TARGETS];
/*
* The black hole device responsible for handling requests for
* disabled luns on enabled targets.
*/
- struct tmode_lstate* black_hole;
+ struct ahc_tmode_lstate *black_hole;
/*
* Device instance currently on the bus awaiting a continue TIO
* for a command that was not given the disconnect priveledge.
*/
- struct tmode_lstate* pending_device;
+ struct ahc_tmode_lstate *pending_device;
/*
* Card characteristics
@@ -936,9 +945,6 @@ struct ahc_softc {
uint8_t our_id;
uint8_t our_id_b;
- /* Targets that need negotiation messages */
- uint16_t targ_msg_req;
-
/*
* PCI error detection.
*/
@@ -1086,6 +1092,7 @@ int ahc_softc_init(struct ahc_softc *,
struct ahc_probe_config*);
void ahc_controller_info(struct ahc_softc *ahc, char *buf);
int ahc_init(struct ahc_softc *ahc);
+void ahc_intr_enable(struct ahc_softc *ahc, int enable);
void ahc_pause_and_flushwork(struct ahc_softc *ahc);
int ahc_suspend(struct ahc_softc *ahc);
int ahc_resume(struct ahc_softc *ahc);
@@ -1149,10 +1156,11 @@ void ahc_validate_width(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
u_int *bus_width,
role_t role);
-void ahc_update_target_msg_request(struct ahc_softc *ahc,
- struct ahc_devinfo *dinfo,
- struct ahc_initiator_tinfo *tinfo,
- int force, int paused);
+int ahc_update_neg_request(struct ahc_softc*,
+ struct ahc_devinfo*,
+ struct ahc_tmode_tstate*,
+ struct ahc_initiator_tinfo*,
+ int /*force*/);
void ahc_set_width(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo,
u_int width, u_int type, int paused);
@@ -1168,16 +1176,14 @@ void ahc_set_tags(struct ahc_softc *ahc,
/**************************** Target Mode *************************************/
#ifdef AHC_TARGET_MODE
void ahc_send_lstate_events(struct ahc_softc *,
- struct tmode_lstate *);
+ struct ahc_tmode_lstate *);
void ahc_handle_en_lun(struct ahc_softc *ahc,
struct cam_sim *sim, union ccb *ccb);
cam_status ahc_find_tmode_devs(struct ahc_softc *ahc,
struct cam_sim *sim, union ccb *ccb,
- struct tmode_tstate **tstate,
- struct tmode_lstate **lstate,
+ struct ahc_tmode_tstate **tstate,
+ struct ahc_tmode_lstate **lstate,
int notfound_failure);
-void ahc_setup_target_msgin(struct ahc_softc *ahc,
- struct ahc_devinfo *devinfo);
#ifndef AHC_TMODE_ENABLE
#define AHC_TMODE_ENABLE 0
#endif
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index ac966f0..c1f342f 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx.reg#14 $
+ * $Id: //depot/src/aic7xxx/aic7xxx.reg#15 $
*
* $FreeBSD$
*/
@@ -1419,15 +1419,6 @@ scratch_ram {
}
/*
- * Interrupt kernel for a message to this target on
- * the next transaction. This is usually used for
- * negotiation requests.
- */
- TARGET_MSG_REQUEST {
- size 2
- }
-
- /*
* Sequences the kernel driver has okayed for us. This allows
* the driver to do things like prevent initiator or target
* operations.
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index 8788e60..bd4342a 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -479,6 +479,9 @@ target_synccmd:
*/
mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
+ test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
+ mvi P_MESGIN|BSYO call change_phase;
+ jmp host_target_message_loop;
target_ITloop:
/*
* Start honoring ATN signals now that
@@ -494,12 +497,12 @@ target_ITloop:
* on the state of NO_DISCONNECT.
*/
test SEQ_FLAGS, NO_DISCONNECT jz target_disconnect;
- if ((ahc->flags & AHC_PAGESCBS) != 0) {
- mov ALLZEROS call get_free_or_disc_scb;
- }
mov RETURN_1, ALLZEROS;
call complete_target_cmd;
cmp RETURN_1, CONT_MSG_LOOP jne .;
+ if ((ahc->flags & AHC_PAGESCBS) != 0) {
+ mov ALLZEROS call get_free_or_disc_scb;
+ }
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov SCB_TAG call dma_scb;
jmp target_synccmd;
@@ -1351,18 +1354,6 @@ p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
test SCB_CONTROL,MK_MESSAGE jnz host_message_loop;
- mov FUNCTION1, SCB_SCSIID;
- mov A, FUNCTION1;
- mov SINDEX, TARGET_MSG_REQUEST[0];
- if ((ahc->features & AHC_TWIN) != 0) {
- /* Second Channel uses high byte bits */
- test SCB_SCSIID, TWIN_CHNLB jz . + 2;
- mov SINDEX, TARGET_MSG_REQUEST[1];
- } else if ((ahc->features & AHC_WIDE) != 0) {
- test SCB_SCSIID, 0x80 jz . + 2; /* target > 7 */
- mov SINDEX, TARGET_MSG_REQUEST[1];
- }
- test SINDEX, A jnz host_message_loop;
p_mesgout_identify:
or SINDEX, MSG_IDENTIFYFLAG|DISCENB, SCB_LUN;
test SCB_CONTROL, DISCENB jnz . + 2;
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c
index 8d9fb21..f61c8da 100644
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.c
+++ b/sys/dev/aic7xxx/aic7xxx_freebsd.c
@@ -288,6 +288,27 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
}
if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
+ struct cam_path *ccb_path;
+
+ /*
+ * If we have finally disconnected, clean up our
+ * pending device state.
+ * XXX - There may be error states that cause where
+ * we will remain connected.
+ */
+ ccb_path = ccb->ccb_h.path;
+ if (ahc->pending_device != NULL
+ && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) {
+
+ if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
+ ahc->pending_device = NULL;
+ } else {
+ xpt_print_path(ccb->ccb_h.path);
+ printf("Still disconnected\n");
+ ahc_freeze_ccb(ccb);
+ }
+ }
+
if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG)
ccb->ccb_h.status |= CAM_REQ_CMP;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
@@ -361,7 +382,7 @@ static void
ahc_action(struct cam_sim *sim, union ccb *ccb)
{
struct ahc_softc *ahc;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_lstate *lstate;
u_int target_id;
u_int our_id;
long s;
@@ -378,7 +399,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
{
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
cam_status status;
status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
@@ -427,6 +448,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
|| ccb->ccb_h.func_code == XPT_RESET_DEV)) {
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
xpt_done(ccb);
+ return;
}
/*
@@ -470,10 +492,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct target_data *tdata;
tdata = &hscb->shared_data.tdata;
- if (ahc->pending_device == lstate) {
+ if (ahc->pending_device == lstate)
scb->flags |= SCB_TARGET_IMMEDIATE;
- ahc->pending_device = NULL;
- }
hscb->control |= TARGET_SCB;
tdata->target_phases = IDENTIFY_SEEN;
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
@@ -481,6 +501,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
tdata->scsi_status =
ccb->csio.scsi_status;
}
+ if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
+ tdata->target_phases |= NO_DISCONNECT;
+
tdata->initiator_tag = ccb->csio.tag_id;
}
if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
@@ -493,8 +516,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_NOTIFY_ACK:
case XPT_IMMED_NOTIFY:
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
cam_status status;
status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
@@ -528,7 +551,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_spi *spi;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
uint16_t *discenable;
uint16_t *tagenable;
u_int update_type;
@@ -652,7 +675,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct ahc_devinfo devinfo;
struct ccb_trans_settings *cts;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
uint16_t *discenable;
uint16_t *tagenable;
u_int update_type;
@@ -895,7 +918,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_spi *spi;
struct ahc_initiator_tinfo *targ_info;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
struct ahc_transinfo *tinfo;
scsi = &cts->proto_specific.scsi;
@@ -954,7 +977,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
#else
struct ahc_devinfo devinfo;
struct ahc_initiator_tinfo *targ_info;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
struct ahc_transinfo *tinfo;
long s;
@@ -1051,7 +1074,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
union ccb *ccb;
struct ahc_softc *ahc;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
u_int mask;
long s;
@@ -1186,7 +1209,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->hscb->scsioffset = tinfo->current.offset;
if ((tstate->ultraenb & mask) != 0)
scb->hscb->control |= ULTRAENB;
-
+
if ((tstate->discenable & mask) != 0
&& (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
scb->hscb->control |= DISCENB;
@@ -1197,6 +1220,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
|| tinfo->goal.ppr_options != 0)) {
scb->flags |= SCB_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
+ } else if ((tstate->auto_negotiate & mask) != 0) {
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
}
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
@@ -1239,6 +1265,8 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->flags |= SCB_ACTIVE;
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
+ /* Define a mapping from our tag to the SCB. */
+ ahc->scb_data->scbindex[scb->hscb->tag] = scb;
ahc_pause(ahc);
if ((ahc->flags & AHC_PAGESCBS) == 0)
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
@@ -1433,27 +1461,9 @@ ahc_timeout(void *arg)
lun = SCB_GET_LUN(scb);
ahc_print_path(ahc, scb);
- printf("SCB 0x%x - timed out ", scb->hscb->tag);
- /*
- * Take a snapshot of the bus state and print out
- * some information so we can track down driver bugs.
- */
- last_phase = ahc_inb(ahc, LASTPHASE);
-
- printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg);
-
- printf(", SEQADDR == 0x%x\n",
- ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
-
- printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n",
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8));
-
- printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0));
-
+ printf("SCB 0x%x - timed out\n", scb->hscb->tag);
ahc_dump_card_state(ahc);
+ last_phase = ahc_inb(ahc, LASTPHASE);
if (scb->sg_count > 0) {
for (i = 0; i < scb->sg_count; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
@@ -1683,8 +1693,8 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
case XPT_IMMED_NOTIFY:
case XPT_CONT_TARGET_IO:
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
struct ccb_hdr_slist *list;
cam_status status;
@@ -1818,7 +1828,6 @@ ahc_platform_free(struct ahc_softc *ahc)
pdata = ahc->platform_data;
if (pdata != NULL) {
- device_printf(ahc->dev_softc, "Platform free\n");
if (pdata->regs != NULL)
bus_release_resource(ahc->dev_softc,
pdata->regs_res_type,
diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h
index 16edaba..446b104 100644
--- a/sys/dev/aic7xxx/aic7xxx_inline.h
+++ b/sys/dev/aic7xxx/aic7xxx_inline.h
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#17 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_inline.h#19 $
*
* $FreeBSD$
*/
@@ -193,7 +193,7 @@ static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc,
char channel, u_int our_id,
u_int remote_id,
- struct tmode_tstate **tstate);
+ struct ahc_tmode_tstate **tstate);
static __inline struct scb*
ahc_get_scb(struct ahc_softc *ahc);
static __inline void ahc_free_scb(struct ahc_softc *ahc, struct scb *scb);
@@ -228,7 +228,7 @@ ahc_check_residual(struct scb *scb)
*/
static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
- u_int remote_id, struct tmode_tstate **tstate)
+ u_int remote_id, struct ahc_tmode_tstate **tstate)
{
/*
* Transfer data structures are stored from the perspective
@@ -433,7 +433,7 @@ ahc_intr(struct ahc_softc *ahc)
if (ahc->unsolicited_ints > 500
&& (ahc->chip & AHC_PCI) != 0
&& (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0)
- ahc_pci_intr(ahc);
+ ahc->bus_intr(ahc);
#endif
}
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index 8d9fb21..f61c8da 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -288,6 +288,27 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
}
if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
+ struct cam_path *ccb_path;
+
+ /*
+ * If we have finally disconnected, clean up our
+ * pending device state.
+ * XXX - There may be error states that cause where
+ * we will remain connected.
+ */
+ ccb_path = ccb->ccb_h.path;
+ if (ahc->pending_device != NULL
+ && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) {
+
+ if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
+ ahc->pending_device = NULL;
+ } else {
+ xpt_print_path(ccb->ccb_h.path);
+ printf("Still disconnected\n");
+ ahc_freeze_ccb(ccb);
+ }
+ }
+
if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG)
ccb->ccb_h.status |= CAM_REQ_CMP;
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
@@ -361,7 +382,7 @@ static void
ahc_action(struct cam_sim *sim, union ccb *ccb)
{
struct ahc_softc *ahc;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_lstate *lstate;
u_int target_id;
u_int our_id;
long s;
@@ -378,7 +399,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
{
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
cam_status status;
status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
@@ -427,6 +448,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
|| ccb->ccb_h.func_code == XPT_RESET_DEV)) {
ccb->ccb_h.status = CAM_PROVIDE_FAIL;
xpt_done(ccb);
+ return;
}
/*
@@ -470,10 +492,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct target_data *tdata;
tdata = &hscb->shared_data.tdata;
- if (ahc->pending_device == lstate) {
+ if (ahc->pending_device == lstate)
scb->flags |= SCB_TARGET_IMMEDIATE;
- ahc->pending_device = NULL;
- }
hscb->control |= TARGET_SCB;
tdata->target_phases = IDENTIFY_SEEN;
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
@@ -481,6 +501,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
tdata->scsi_status =
ccb->csio.scsi_status;
}
+ if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
+ tdata->target_phases |= NO_DISCONNECT;
+
tdata->initiator_tag = ccb->csio.tag_id;
}
if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
@@ -493,8 +516,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
case XPT_NOTIFY_ACK:
case XPT_IMMED_NOTIFY:
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
cam_status status;
status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
@@ -528,7 +551,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_spi *spi;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
uint16_t *discenable;
uint16_t *tagenable;
u_int update_type;
@@ -652,7 +675,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
struct ahc_devinfo devinfo;
struct ccb_trans_settings *cts;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
uint16_t *discenable;
uint16_t *tagenable;
u_int update_type;
@@ -895,7 +918,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_spi *spi;
struct ahc_initiator_tinfo *targ_info;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
struct ahc_transinfo *tinfo;
scsi = &cts->proto_specific.scsi;
@@ -954,7 +977,7 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
#else
struct ahc_devinfo devinfo;
struct ahc_initiator_tinfo *targ_info;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
struct ahc_transinfo *tinfo;
long s;
@@ -1051,7 +1074,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
union ccb *ccb;
struct ahc_softc *ahc;
struct ahc_initiator_tinfo *tinfo;
- struct tmode_tstate *tstate;
+ struct ahc_tmode_tstate *tstate;
u_int mask;
long s;
@@ -1186,7 +1209,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->hscb->scsioffset = tinfo->current.offset;
if ((tstate->ultraenb & mask) != 0)
scb->hscb->control |= ULTRAENB;
-
+
if ((tstate->discenable & mask) != 0
&& (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
scb->hscb->control |= DISCENB;
@@ -1197,6 +1220,9 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
|| tinfo->goal.ppr_options != 0)) {
scb->flags |= SCB_NEGOTIATE;
scb->hscb->control |= MK_MESSAGE;
+ } else if ((tstate->auto_negotiate & mask) != 0) {
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
}
LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
@@ -1239,6 +1265,8 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->flags |= SCB_ACTIVE;
if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
+ /* Define a mapping from our tag to the SCB. */
+ ahc->scb_data->scbindex[scb->hscb->tag] = scb;
ahc_pause(ahc);
if ((ahc->flags & AHC_PAGESCBS) == 0)
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
@@ -1433,27 +1461,9 @@ ahc_timeout(void *arg)
lun = SCB_GET_LUN(scb);
ahc_print_path(ahc, scb);
- printf("SCB 0x%x - timed out ", scb->hscb->tag);
- /*
- * Take a snapshot of the bus state and print out
- * some information so we can track down driver bugs.
- */
- last_phase = ahc_inb(ahc, LASTPHASE);
-
- printf("%s", ahc_lookup_phase_entry(last_phase)->phasemsg);
-
- printf(", SEQADDR == 0x%x\n",
- ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
-
- printf("STACK == 0x%x, 0x%x, 0x%x, 0x%x\n",
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8),
- ahc_inb(ahc, STACK) | (ahc_inb(ahc, STACK) << 8));
-
- printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0));
-
+ printf("SCB 0x%x - timed out\n", scb->hscb->tag);
ahc_dump_card_state(ahc);
+ last_phase = ahc_inb(ahc, LASTPHASE);
if (scb->sg_count > 0) {
for (i = 0; i < scb->sg_count; i++) {
printf("sg[%d] - Addr 0x%x : Length %d\n",
@@ -1683,8 +1693,8 @@ ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
case XPT_IMMED_NOTIFY:
case XPT_CONT_TARGET_IO:
{
- struct tmode_tstate *tstate;
- struct tmode_lstate *lstate;
+ struct ahc_tmode_tstate *tstate;
+ struct ahc_tmode_lstate *lstate;
struct ccb_hdr_slist *list;
cam_status status;
@@ -1818,7 +1828,6 @@ ahc_platform_free(struct ahc_softc *ahc)
pdata = ahc->platform_data;
if (pdata != NULL) {
- device_printf(ahc->dev_softc, "Platform free\n");
if (pdata->regs != NULL)
bus_release_resource(ahc->dev_softc,
pdata->regs_res_type,
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index 02a73d4..5102c5b 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#19 $
+ * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#21 $
*
* $FreeBSD$
*/
@@ -759,6 +759,8 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
if (error != 0)
return (error);
+ ahc->bus_intr = ahc_pci_intr;
+
/* Remeber how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
ahc_pause(ahc);
@@ -795,6 +797,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
error = ahc_pci_map_int(ahc);
if (error != 0)
return (error);
+
dscommand0 = ahc_inb(ahc, DSCOMMAND0);
dscommand0 |= MPARCKEN|CACHETHEN;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -901,6 +904,11 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
*/
ahc_softc_insert(ahc);
+ /*
+ * Allow interrupts now that we are completely setup.
+ */
+ ahc_intr_enable(ahc, TRUE);
+
return (0);
}
OpenPOWER on IntegriCloud