During a rather lengthy debug session with Markus Kilbinger (Thanks again!),

we managed to kill the following SCSI-driver bugs for the Falcon:
   - The Byte_Count_zero bit of the falcon DMA controller does not always
     tell the truth! This caused the SCSI-driver to choke on devices that
     disconnected in the middle of a DMA-transfer (mostly removables).
   - Printing debug info about the 5380 on the Falcon is *only* permitted
     when DMA is not active.
   - Some functions forgot to remove possibly pending sofware interrupts
   - Some debug options didn't allow debugging a single target while they
     could easily be made to do so. This is fixed.
This commit is contained in:
leo 1996-07-05 19:35:35 +00:00
parent f1af6a2252
commit 4b5bff0d0f
3 changed files with 88 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: atari5380.c,v 1.15 1996/06/18 11:10:04 leo Exp $ */
/* $NetBSD: atari5380.c,v 1.16 1996/07/05 19:35:35 leo Exp $ */
/*
* Copyright (c) 1995 Leo Weppelman.
@ -184,6 +184,7 @@ static struct ncr_softc *cur_softc;
#define wrong_dma_range(r,d) tt_wrong_dma_range(r, d)
#define poll_edma(reqp) tt_poll_edma(reqp)
#define get_dma_result(r, b) tt_get_dma_result(r, b)
#define can_access_5380() 1
#define fair_to_keep_dma() 1
#define claimed_dma() 1
@ -449,6 +450,7 @@ tt_get_dma_result(SC_REQ *reqp, u_long *bytes_left)
#define wrong_dma_range(r,d) falcon_wrong_dma_range(r, d)
#define poll_edma(reqp) falcon_poll_edma(reqp)
#define get_dma_result(r, b) falcon_get_dma_result(r, b)
#define can_access_5380() falcon_can_access_5380()
#define fair_to_keep_dma() (!st_dmawanted())
#define claimed_dma() falcon_claimed_dma()
@ -469,6 +471,7 @@ static void fal1_dma __P((u_int, u_int, SC_REQ *));
static void scsi_falcon_dmasetup __P((SC_REQ *, u_int, u_char));
static int falcon_poll_edma __P((SC_REQ *));
static int falcon_get_dma_result __P((SC_REQ *, u_long *));
int falcon_can_access_5380 __P((void));
void scsi_falcon_clr_ipend __P((void));
void scsi_falcon_idisable __P((void));
void scsi_falcon_ienable __P((void));
@ -535,6 +538,12 @@ scsi_falcon_ipending()
*/
if (MFP->mf_gpip & IO_DINT)
return (0); /* XXX: Actually: we're not allowed to check */
/* LWP: 28-06, must be a dma interrupt! should the
* ST-DMA unit be taken out of dma mode?????
*/
DMA->dma_mode = 0x90;
}
return(get_falcon_5380_reg(NCR5380_DMSTAT) & SC_IRQ_SET);
}
@ -693,30 +702,39 @@ u_long *bytes_left;
reqp->xs->error = XS_DRIVER_STUFFUP;
rv = 1;
}
if (st_dmastat & 0x02) {
/*
* Bytecount not zero.... As the fifo loads in 16 byte
* chunks, check if bytes are stuck in fifo.
* As we don't use DMA on chunks less than 512 bytes
* on the Falcon, report any residual not a multiple of
* 512 as an error...
*/
bytes_done = st_dmaaddr_get() - reqp->dm_cur->dm_addr;
if (bytes_done & 511) {
ncr_tprint(reqp, "%ld bytes of %ld stuck in fifo\n",
bytes_done & 15, bytes_done & ~511);
bytes_done &= ~511;
reqp->xs->error = XS_DRIVER_STUFFUP;
/*
* Because we NEVER start DMA on the Falcon when the data size
* is not a multiple of 512 bytes, we can safely round down the
* byte count on writes. We need to because in case of a disconnect,
* the DMA has already prefetched the next couple of bytes.
* On read, these byte counts are an error. They are logged and
* should be handled by the mi-part of the driver.
* NOTE: We formerly did this by using the 'byte-count-zero' bit
* of the DMA controller, but this didn't seem to work???
* [lwp 29/06/96]
*/
bytes_done = st_dmaaddr_get() - reqp->dm_cur->dm_addr;
if (bytes_done & 511) {
if (PH_IN(reqp->phase)) {
ncr_tprint(reqp, "Byte count on read not a multiple "
"of 512 (%ld)\n", bytes_done);
}
*bytes_left = reqp->dm_cur->dm_count - bytes_done;
bytes_done &= ~511;
}
else {
*bytes_left = 0;
if ((*bytes_left = reqp->dm_cur->dm_count - bytes_done) == 0)
rv = 1;
}
return(rv);
}
static int
falcon_can_access_5380()
{
if (connected && (connected->dr_flag & DRIVER_IN_DMA)
&& (MFP->mf_gpip & IO_DINT))
return(0);
return(1);
}
#endif /* defined(FALCON_SCSI) */
#if defined(TT_SCSI) && defined(FALCON_SCSI)
@ -736,6 +754,7 @@ static void scsi_mach_init __P((struct ncr_softc *));
int wrong_dma_range __P((SC_REQ *, struct dma_chain *));
int poll_edma __P((SC_REQ *));
int get_dma_result __P((SC_REQ *, u_long *));
int can_access_5380 __P((void));
/*
* Register access will be done through the following 2 function pointers.
@ -834,6 +853,14 @@ u_long *bytes_left;
else return(tt_get_dma_result(reqp, bytes_left));
}
extern __inline__ int
can_access_5380()
{
if (machineid & ATARI_FALCON)
return(falcon_can_access_5380());
return(1);
}
/*
* Locking stuff. All turns into NOP's on the TT.
*/
@ -899,6 +926,7 @@ scsi_ctrl(int sr)
else {
spl1();
ncr_ctrl_intr(cur_softc);
spl0();
}
}
}
@ -919,6 +947,7 @@ scsi_dma(int sr)
else {
spl1();
ncr_dma_intr(cur_softc);
spl0();
}
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ncr5380.c,v 1.20 1996/05/15 09:21:51 leo Exp $ */
/* $NetBSD: ncr5380.c,v 1.21 1996/07/05 19:35:38 leo Exp $ */
/*
* Copyright (c) 1995 Leo Weppelman.
@ -180,7 +180,7 @@ extern __inline__ void finish_req(SC_REQ *reqp)
show_request(reqp, "DONE");
#endif
#ifdef DBG_ERR_RET
if (reqp->xs->error != 0)
if ((dbg_target_mask & (1 << reqp->targ_id)) && (reqp->xs->error != 0))
show_request(reqp, "ERR_RET");
#endif
/*
@ -599,6 +599,7 @@ connected:
}
}
/* NEVER TO REACH HERE */
show_phase(NULL, 0); /* XXX: Get rid of not used warning */
panic("ncr5380-SCSI: not designed to come here");
main_exit:
@ -640,7 +641,6 @@ main_exit:
}
}
reconsider_dma();
main_running = 0;
splx(sps);
PID("scsi_main5");
@ -686,6 +686,9 @@ struct ncr_softc *sc;
{
int itype;
if (main_running)
return; /* scsi_main() should handle this one */
while (scsi_ipending()) {
scsi_idisable();
if ((itype = check_intr(sc)) != INTR_SPURIOUS) {
@ -1020,7 +1023,10 @@ struct ncr_softc *sc;
phase = (tmp >> 2) & 7;
if (phase != reqp->phase) {
reqp->phase = phase;
DBG_INFPRINT(show_phase, reqp, phase);
#ifdef DBG_INF
if (dbg_target_mask & (1 << reqp->targ_id))
DBG_INFPRINT(show_phase, reqp, phase);
#endif
}
else {
/*
@ -1030,6 +1036,7 @@ struct ncr_softc *sc;
&& ((phase == PH_DATAOUT) || (phase == PH_DATAIN))) {
busy &= ~(1 << reqp->targ_id);
connected = NULL;
reqp->xs->error = XS_TIMEOUT;
finish_req(reqp);
scsi_reset_verbose(sc, "Failure to abort command");
return (0);
@ -1387,11 +1394,11 @@ int dont_drop_ack;
SET_5380_REG(NCR5380_TCOM, ph);
do {
if (!wait_req_true()) {
DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
DBG_PIOPRINT ("SCSI: transfer_pio: missing REQ\n", 0, 0);
break;
}
if (((GET_5380_REG(NCR5380_IDSTAT) >> 2) & 7) != ph) {
DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
DBG_PIOPRINT ("SCSI: transfer_pio: phase mismatch\n", 0, 0);
break;
}
if (PH_IN(ph)) {
@ -1442,6 +1449,7 @@ int dont_drop_ack;
}
#ifdef REAL_DMA
/*
* Start a DMA-transfer on the device using the current pointers.
* If 'poll' is true, the function busy-waits until DMA has completed.
@ -1704,6 +1712,7 @@ u_long len;
}
else {
SET_5380_REG(NCR5380_DATA, 0);
SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ATN);
SET_5380_REG(NCR5380_ICOM, SC_ADTB|SC_A_ACK|SC_A_ATN);
}
if (!wait_req_false())
@ -1718,6 +1727,9 @@ u_long len;
"%ld bytes.\n", len - n);
return (0);
}
ncr_aprint(sc, "Phase now: %d after %ld bytes.\n", phase,
len - n);
}
return (-1);
}
@ -1805,9 +1817,9 @@ struct ncr_softc *sc;
return (INTR_DMA);
}
}
scsi_clr_ipend();
printf("-->");
scsi_show();
scsi_clr_ipend();
ncr_aprint(sc, "Spurious interrupt.\n");
return (INTR_SPURIOUS);
}
@ -1961,6 +1973,19 @@ ncr_aprint(struct ncr_softc *sc, char *fmt, ...)
/****************************************************************************
* Start Debugging Functions *
****************************************************************************/
static char *phase_names[] = {
"DATA_OUT", "DATA_IN", "COMMAND", "STATUS", "NONE", "NONE", "MSG_OUT",
"MSG_IN"
};
static void
show_phase(reqp, phase)
SC_REQ *reqp;
int phase;
{
printf("INFTRANS: %d Phase = %s\n", reqp->targ_id, phase_names[phase]);
}
static void
show_data_sense(xs)
struct scsi_xfer *xs;
@ -2038,9 +2063,12 @@ scsi_show()
show_request(tmp, "DISCONNECTED");
if (connected)
show_request(connected, "CONNECTED");
idstat = GET_5380_REG(NCR5380_IDSTAT);
dmstat = GET_5380_REG(NCR5380_DMSTAT);
show_signals(dmstat, idstat);
if (can_access_5380()) {
idstat = GET_5380_REG(NCR5380_IDSTAT);
dmstat = GET_5380_REG(NCR5380_DMSTAT);
show_signals(dmstat, idstat);
}
if (connected)
printf("phase = %d, ", connected->phase);
printf("busy:%x, spl:%04x\n", busy, sps);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ncr5380reg.h,v 1.10 1996/05/15 09:21:53 leo Exp $ */
/* $NetBSD: ncr5380reg.h,v 1.11 1996/07/05 19:35:40 leo Exp $ */
/*
* Copyright (c) 1995 Leo Weppelman.
@ -249,6 +249,7 @@ static void scsi_main __P((struct ncr_softc *));
static void scsi_reset_verbose __P((struct ncr_softc *, const char *));
static int scsi_select __P((SC_REQ *, int));
static void show_data_sense __P((struct scsi_xfer *));
static void show_phase __P((SC_REQ *, int));
static void show_request __P((SC_REQ *, char *));
static void show_signals __P((u_char, u_char));
static void transfer_dma __P((SC_REQ *, u_int, int));
@ -261,6 +262,5 @@ static int wait_req_true __P((void));
*/
void scsi_show __P((void));
void scsi_reset __P((void));
/* static void show_phase __P((SC_REQ *, int)); */
#endif /* _NCR5380REG_H */