From 0e5fe20560b9aa5d4cf9be4d1b6eb0eb7107a2c8 Mon Sep 17 00:00:00 2001 From: leo Date: Sun, 8 Oct 1995 13:34:23 +0000 Subject: [PATCH] - Cleanup the arbitration - Make sure the MON_BUSY flag is cleared after a DMA transfer. Otherwise we might end up with a 'lost-busy' situation unexpectedly. This will prevent the 5380 from driving the bus, which is not funny during reselections. --- sys/arch/atari/dev/ncr5380.c | 94 ++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/sys/arch/atari/dev/ncr5380.c b/sys/arch/atari/dev/ncr5380.c index 9bc5572833da..5d88a1f8c68c 100644 --- a/sys/arch/atari/dev/ncr5380.c +++ b/sys/arch/atari/dev/ncr5380.c @@ -1,4 +1,4 @@ -/* $NetBSD: ncr5380.c,v 1.10 1995/10/05 08:52:58 leo Exp $ */ +/* $NetBSD: ncr5380.c,v 1.11 1995/10/08 13:34:23 leo Exp $ */ /* * Copyright (c) 1995 Leo Weppelman. @@ -711,7 +711,7 @@ SC_REQ *reqp; * Interrupts are lowered when the 5380 is setup to arbitrate for the * bus. */ - if (connected || (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) { + if (connected) { splx(sps); PID("scsi_select2"); return (-1); @@ -732,34 +732,15 @@ SC_REQ *reqp; splx(sps); - cnt = 10000; + cnt = 10; while (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP) && --cnt) delay(1); if (!(GET_5380_REG(NCR5380_ICOM) & SC_AIP)) { SET_5380_REG(NCR5380_MODE, IMODE_BASE); - delay(1); + SET_5380_REG(NCR5380_ICOM, 0); + DBG_SELPRINT ("Arbitration lost, bus not free\n",0); PID("scsi_select3"); - - if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) { - /* - * Damn, we have a connected target that we don't know - * of. Some targets seem to respond to a selection - * AFTER the selection-timeout. Try to get the target - * into the Message-out phase so we can send an ABORT - * message. We try to avoid resetting the SCSI-bus! - */ - if (!reach_msg_out(sc, sizeof(struct scsi_generic))) { - u_long len = 1; - u_char phase = PH_MSGOUT; - u_char msg = MSG_ABORT; - - transfer_pio(&phase, &msg, &len, 0); - } - else if (GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) - scsi_reset(sc); - } - PID("scsi_select4"); return (-1); } @@ -770,36 +751,47 @@ SC_REQ *reqp; * Check the result of the arbitration. If we failed, return -1. */ if (GET_5380_REG(NCR5380_ICOM) & SC_LA) { - /* - * The spec requires that we should read the data register to - * check for higher id's and check the SC_LA again. - */ - tmp[0] = GET_5380_REG(NCR5380_DATA); - if (GET_5380_REG(NCR5380_ICOM) & SC_LA) { - SET_5380_REG(NCR5380_MODE, IMODE_BASE); - SET_5380_REG(NCR5380_ICOM, 0); - DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0); - PID("scsi_select5"); - return (-1); - } + SET_5380_REG(NCR5380_MODE, IMODE_BASE); + SET_5380_REG(NCR5380_ICOM, 0); + PID("scsi_select4"); + return (-1); + } + + /* + * The spec requires that we should read the data register to + * check for higher id's and check the SC_LA again. + */ + tmp[0] = GET_5380_REG(NCR5380_DATA); + if (tmp[0] & ~((SC_HOST_ID << 1) - 1)) { + SET_5380_REG(NCR5380_MODE, IMODE_BASE); + SET_5380_REG(NCR5380_ICOM, 0); + DBG_SELPRINT ("Arbitration lost, higher id present\n",0); + PID("scsi_select5"); + return (-1); + } + if (GET_5380_REG(NCR5380_ICOM) & SC_LA) { + SET_5380_REG(NCR5380_MODE, IMODE_BASE); + SET_5380_REG(NCR5380_ICOM, 0); + DBG_SELPRINT ("Arbitration lost,deassert SC_ARBIT\n",0); + PID("scsi_select6"); + return (-1); } SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_BSY); if (GET_5380_REG(NCR5380_ICOM) & SC_LA) { SET_5380_REG(NCR5380_MODE, IMODE_BASE); SET_5380_REG(NCR5380_ICOM, 0); DBG_SELPRINT ("Arbitration lost, deassert SC_A_SEL\n", 0); - PID("scsi_select6"); + PID("scsi_select7"); return (-1); } /* Bus settle delay + Bus clear delay = 1.2 usecs */ delay(2); DBG_SELPRINT ("Arbitration complete\n", 0); - targ_bit = 1 << reqp->targ_id; - /* * Now that we won the arbitration, start the selection. */ + targ_bit = 1 << reqp->targ_id; SET_5380_REG(NCR5380_DATA, SC_HOST_ID | targ_bit); if (sc->sc_noselatn & targ_bit) @@ -832,7 +824,7 @@ SC_REQ *reqp; * Wait for the target to react, the specs call for a timeout of * 250 ms. */ - cnt = 25000 /* 250 */; + cnt = 25000; while (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY) && --cnt) delay(10); @@ -845,7 +837,7 @@ SC_REQ *reqp; * When BSY is asserted, we assume the selection succeeded, * otherwise we release the bus. */ - SET_5380_REG(NCR5380_ICOM, SC_A_SEL | SC_A_ATN); + SET_5380_REG(NCR5380_ICOM, SC_A_SEL | atn_flag); delay(201); if (!(GET_5380_REG(NCR5380_IDSTAT) & SC_S_BSY)) { SET_5380_REG(NCR5380_ICOM, 0); @@ -853,7 +845,7 @@ SC_REQ *reqp; DBG_SELPRINT ("Target %d not responding to sel\n", reqp->targ_id); finish_req(reqp); - PID("scsi_select7"); + PID("scsi_select8"); return (0); } } @@ -921,7 +913,7 @@ SC_REQ *reqp; SET_5380_REG(NCR5380_ICOM, 0); reqp->xs->error = code ? code : XS_DRIVER_STUFFUP; finish_req(reqp); - PID("scsi_select8"); + PID("scsi_select9"); return (0); } reqp->phase = PH_MSGOUT; @@ -938,7 +930,7 @@ identify_failed: connected = reqp; busy |= targ_bit; - PID("scsi_select9"); + PID("scsi_select10"); return (0); } @@ -986,7 +978,6 @@ information_transfer() switch (phase) { case PH_DATAOUT: - #ifdef DBG_NOWRITE ncr_tprint(reqp, "NOWRITE set -- write attempt aborted."); reqp->msgout = MSG_ABORT; @@ -1198,6 +1189,13 @@ struct ncr_softc *sc; SET_5380_REG(NCR5380_ICOM, SC_A_BSY); len = 1000; while ((GET_5380_REG(NCR5380_IDSTAT) & SC_S_SEL) && (len > 0)) { + if(!GET_5380_REG(NCR5380_DATA)) { + /* + * We stepped into the reselection timeout.... + */ + SET_5380_REG(NCR5380_ICOM, 0); + return; + } delay(1); len--; } @@ -1457,9 +1455,11 @@ dma_ready() /* * DMA mode should always be reset even when we will continue with the - * next chain. + * next chain. It is also essential to clear the MON_BUSY because + * when LOST_BUSY is unexpectedly set, we will not be able to drive + * the bus.... */ - SET_5380_REG(NCR5380_MODE, GET_5380_REG(NCR5380_MODE) & ~SC_M_DMA); + SET_5380_REG(NCR5380_MODE, IMODE_BASE); if ((dmstat & SC_BSY_ERR) || !(dmstat & SC_PHS_MTCH)