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:
parent
f1af6a2252
commit
4b5bff0d0f
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user