mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Update scsi code to the latest from Julian. This code is now identical
to the last copy from Julian. After this commit I will be commiting the local fixes and makeing diffs to send back to Julian so he can update his code. ---- >From julian@jules.DIALix.oz.au Thu Aug 5 09:25:23 1993 To: hd@world.std.com, julian@jules.DIALix.oz.au Cc: nate@bsd.coe.montana.edu Subject: Re: new scsi ---- >From julian@jules.DIALix.oz.au Sat Aug 7 04:13:17 1993 To: hd@world.std.com (HD Associates) Cc: nate@bsd.coe.montana.edu Subject: Re: timeout diffs Here are the diffs to take the scsi stuff to my latest tree from what Nate and you received.. the changes remove all the local timeout stuff and use (un)timeout(), ---- >From julian@jules.DIALix.oz.au Sat Aug 7 04:13:45 1993 To: hd@world.std.com (HD Associates) Cc: nate@bsd.coe.montana.edu, briggs@csugrad.cs.vt.edu here is a fix for a silly bug in the scsiconf I just sent out and a similar fix for st.c
This commit is contained in:
parent
3c4067ef4d
commit
b6105e6d2a
5 changed files with 469 additions and 1002 deletions
|
|
@ -11,41 +11,15 @@
|
|||
* TFS supplies this software to be publicly redistributed
|
||||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*/
|
||||
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log: aha1742.c,v $
|
||||
* Revision 1.4 1993/08/06 11:59:02 rgrimes
|
||||
* Fixed **probing for scsi devices** message to have a controller and unit
|
||||
* message on the begining of it:
|
||||
* aha0: **probing for scsi devices**
|
||||
*
|
||||
* Revision 1.3 1993/07/29 11:55:34 nate
|
||||
* Syncing our sources back with Julian's, and removing PATCHKIT headers.
|
||||
*
|
||||
* Large Bustek changes, most everything else is minimal.
|
||||
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
|
||||
* -------------------- ----- ----------------------
|
||||
* CURRENT PATCH LEVEL: 1 00098
|
||||
* -------------------- ----- ----------------------
|
||||
*
|
||||
* Revision 1.2 1993/07/15 17:52:58 davidg
|
||||
* Modified attach printf's so that the output is compatible with the "new"
|
||||
* way of doing things. There still remain several drivers that need to
|
||||
* be updated. Also added a compile-time option to pccons to switch the
|
||||
* control and caps-lock keys (REVERSE_CAPS_CTRL) - added for my personal
|
||||
* sanity.
|
||||
*
|
||||
* Revision 1.1.1.1 1993/06/12 14:57:59 rgrimes
|
||||
* Initial import, 0.1 + pk 0.2.4-B1
|
||||
*
|
||||
* julian - removed un-necessary splx() calls and debugging code
|
||||
*
|
||||
* Revision 1.3 93/05/22 16:51:18 julian
|
||||
* set up dev->dev_pic before it's needed for OSF
|
||||
*
|
||||
* Revision 1.2 93/05/07 11:40:27 julian
|
||||
* fixed SLEEPTIME calculation
|
||||
*
|
||||
* Revision 1.1 93/05/07 11:14:03 julian
|
||||
* Initial revision
|
||||
* 16 Feb 93 Julian Elischer ADDED for SCSI system
|
||||
* commenced: Sun Sep 27 18:14:01 PDT 1992
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
@ -103,6 +77,7 @@ int Debugger();
|
|||
#endif MACH
|
||||
|
||||
typedef unsigned long int physaddr;
|
||||
extern int hz;
|
||||
|
||||
#ifdef MACH
|
||||
extern physaddr kvtophys();
|
||||
|
|
@ -297,8 +272,6 @@ struct ecb
|
|||
/*-----------------end of hardware supported fields----------------*/
|
||||
struct ecb *next; /* in free list */
|
||||
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
|
||||
long int delta; /* difference from previous*/
|
||||
struct ecb *later,*sooner;
|
||||
int flags;
|
||||
#define ECB_FREE 0
|
||||
#define ECB_ACTIVE 1
|
||||
|
|
@ -310,9 +283,6 @@ struct ecb
|
|||
struct scsi_sense_data ecb_sense;
|
||||
};
|
||||
|
||||
struct ecb *ahb_soonest = (struct ecb *)0;
|
||||
struct ecb *ahb_latest = (struct ecb *)0;
|
||||
long int ahb_furtherest = 0; /* longest time in the timeout queue */
|
||||
/**/
|
||||
|
||||
struct ahb_data
|
||||
|
|
@ -546,6 +516,7 @@ struct isa_dev *dev;
|
|||
#ifdef __386BSD__ /* 386BSD */
|
||||
dev->id_irq = (1 << ahb_data[unit].vect);
|
||||
dev->id_drq = -1; /* use EISA dma */
|
||||
printf("\n **");
|
||||
#endif __386BSD__
|
||||
|
||||
ahb_unit++;
|
||||
|
|
@ -562,7 +533,7 @@ struct isa_dev *dev;
|
|||
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d: **probing for scsi devices**\n", unit);
|
||||
printf(" probing for scsi devices**\n");
|
||||
#endif __386BSD__
|
||||
|
||||
/***********************************************\
|
||||
|
|
@ -572,10 +543,9 @@ struct isa_dev *dev;
|
|||
#if defined(OSF)
|
||||
ahb_attached[unit]=1;
|
||||
#endif /* defined(OSF) */
|
||||
if(!unit) /* only one for all boards */
|
||||
{
|
||||
ahb_timeout(0);
|
||||
}
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d",unit);
|
||||
#endif __386BSD__
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -603,8 +573,10 @@ ahbintr(unit)
|
|||
|
||||
int port = ahb_data[unit].baseport;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ahbintr ");
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
#if defined(OSF)
|
||||
if (!ahb_attached[unit])
|
||||
|
|
@ -623,8 +595,10 @@ ahbintr(unit)
|
|||
stat = ahbstat & G2INTST_INT_STAT;
|
||||
mboxval = inl(port + MBOXIN0);/* don't know this will work */
|
||||
outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("status = 0x%x ",stat);
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* Process the completed operation *
|
||||
\***********************************************/
|
||||
|
|
@ -647,13 +621,9 @@ ahbintr(unit)
|
|||
ahb_data[unit].immed_ecb = 0;
|
||||
break;
|
||||
case AHB_ASN: /* for target mode */
|
||||
printf("ahb%d: Unexpected ASN interrupt(%x)\n",
|
||||
unit, mboxval);
|
||||
ecb = 0;
|
||||
break;
|
||||
case AHB_HW_ERR:
|
||||
printf("ahb%d: Hardware error interrupt(%x)\n",
|
||||
unit, mboxval);
|
||||
ecb = 0;
|
||||
break;
|
||||
case AHB_ECB_RECOVERED:
|
||||
|
|
@ -669,13 +639,15 @@ ahbintr(unit)
|
|||
}
|
||||
if(ecb)
|
||||
{
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWCMDS )
|
||||
{
|
||||
ahb_show_scsi_cmd(ecb->xs);
|
||||
}
|
||||
if((ahb_debug & AHB_SHOWECBS) && ecb)
|
||||
printf("<int ecb(%x)>",ecb);
|
||||
ahb_remove_timeout(ecb);
|
||||
#endif /*AHBDEBUG*/
|
||||
untimeout(ahb_timeout,ecb);
|
||||
ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL));
|
||||
}
|
||||
}
|
||||
|
|
@ -695,8 +667,10 @@ struct ecb *ecb;
|
|||
struct scsi_sense_data *s1,*s2;
|
||||
struct scsi_xfer *xs = ecb->xs;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
|
||||
printf("ahb_done ");
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* Otherwise, put the results of the operation *
|
||||
* into the xfer and call whoever started it *
|
||||
|
|
@ -732,19 +706,23 @@ struct ecb *ecb;
|
|||
case HS_CMD_ABORTED_ADAPTER: /* No response */
|
||||
break;
|
||||
case HS_TIMED_OUT: /* No response */
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("timeout reported back\n");
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
xs->error = XS_TIMEOUT;
|
||||
break;
|
||||
default: /* Other scsi protocol messes */
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("unexpected ha_status: %x\n",
|
||||
stat->ha_status);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -761,11 +739,13 @@ struct ecb *ecb;
|
|||
xs->error = XS_BUSY;
|
||||
break;
|
||||
default:
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("unexpected targ_status: %x\n",
|
||||
stat->targ_status);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
|
|
@ -785,8 +765,10 @@ struct ecb *ecb;
|
|||
{
|
||||
unsigned int opri;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ecb%d(0x%x)> ",unit,flags);
|
||||
#endif /*AHBDEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
|
||||
|
|
@ -813,8 +795,10 @@ ahb_get_ecb(unit,flags)
|
|||
unsigned opri;
|
||||
struct ecb *rc;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("<ecb%d(0x%x) ",unit,flags);
|
||||
#endif /*AHBDEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
/***********************************************\
|
||||
|
|
@ -865,8 +849,10 @@ int unit;
|
|||
&& (spincount--));
|
||||
if(spincount == -1)
|
||||
{
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
printf("ahb_init: No answer from bt742a board\n");
|
||||
#endif /*AHBDEBUG*/
|
||||
return(ENXIO);
|
||||
}
|
||||
i = inb(port + MBOXIN0) & 0xff;
|
||||
|
|
@ -890,6 +876,7 @@ int unit;
|
|||
* level *
|
||||
\***********************************************/
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d reading board settings, ",unit);
|
||||
#define PRNT(x)
|
||||
#else __386BSD__
|
||||
printf("ahb%d:",unit);
|
||||
|
|
@ -988,8 +975,10 @@ struct scsi_xfer *xs;
|
|||
int bytes_this_seg,bytes_this_page,datalen,flags;
|
||||
struct iovec *iovp;
|
||||
int s;
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ahb_scsi_cmd ");
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* get a ecb (mbox-out) to use. If the transfer *
|
||||
* is from a buf (possibly from interrupt time) *
|
||||
|
|
@ -1014,12 +1003,14 @@ struct scsi_xfer *xs;
|
|||
}
|
||||
|
||||
cheat = ecb;
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
printf("<start ecb(%x)>",ecb);
|
||||
if(scsi_debug & SHOWCOMMANDS)
|
||||
{
|
||||
ahb_show_scsi_cmd(xs);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
ecb->xs = xs;
|
||||
/***********************************************\
|
||||
* If it's a reset, we need to do an 'immediate' *
|
||||
|
|
@ -1039,7 +1030,7 @@ cheat = ecb;
|
|||
{
|
||||
s = splbio();
|
||||
ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
|
||||
ahb_add_timeout(ecb,xs->timeout);
|
||||
timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
|
||||
splx(s);
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
|
|
@ -1049,8 +1040,10 @@ cheat = ecb;
|
|||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("wait ");
|
||||
#endif /*AHBDEBUG*/
|
||||
if( ahb_poll(unit,xs->timeout))
|
||||
{
|
||||
ahb_free_ecb(unit,ecb,flags);
|
||||
|
|
@ -1089,10 +1082,12 @@ cheat = ecb;
|
|||
{
|
||||
sg->addr = (physaddr)iovp->iov_base;
|
||||
xs->datalen += sg->len = iovp->iov_len;
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x@0x%x)"
|
||||
,iovp->iov_len
|
||||
,iovp->iov_base);
|
||||
#endif /*AHBDEBUG*/
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
|
|
@ -1105,8 +1100,10 @@ cheat = ecb;
|
|||
* Set up the scatter gather block *
|
||||
\***********************************************/
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("%d @0x%x:- ",xs->datalen,xs->data);
|
||||
#endif /*AHBDEBUG*/
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
|
@ -1118,8 +1115,10 @@ cheat = ecb;
|
|||
/* put in the base address */
|
||||
sg->addr = thisphys;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("0x%x",thisphys);
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
|
|
@ -1148,16 +1147,20 @@ cheat = ecb;
|
|||
/********************************************\
|
||||
* next page isn't contiguous, finish the seg *
|
||||
\********************************************/
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x)",bytes_this_seg);
|
||||
#endif /*AHBDEBUG*/
|
||||
sg->len = bytes_this_seg;
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
} /*end of iov/kv decision */
|
||||
ecb->datalen = seg * sizeof(struct ahb_dma_seg);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("\n");
|
||||
#endif /*AHBDEBUG*/
|
||||
if (datalen)
|
||||
{ /* there's still data, must have run out of segs! */
|
||||
printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
|
||||
|
|
@ -1185,18 +1188,22 @@ cheat = ecb;
|
|||
{
|
||||
s = splbio();
|
||||
ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
|
||||
ahb_add_timeout(ecb,xs->timeout);
|
||||
timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
|
||||
splx(s);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_sent ");
|
||||
#endif /*AHBDEBUG*/
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_wait ");
|
||||
#endif /*AHBDEBUG*/
|
||||
do
|
||||
{
|
||||
if(ahb_poll(unit,xs->timeout))
|
||||
|
|
@ -1219,172 +1226,55 @@ cheat = ecb;
|
|||
return(COMPLETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* +----------+ +----------+ +----------+
|
||||
* ahb_soonest--->| later |--->| later|--->| later|--->0
|
||||
* | [Delta] | | [Delta] | | [Delta] |
|
||||
* 0<---|sooner |<---|sooner |<---|sooner |<---ahb_latest
|
||||
* +----------+ +----------+ +----------+
|
||||
*
|
||||
* ahb_furtherest = sum(Delta[1..n])
|
||||
*/
|
||||
ahb_add_timeout(ecb,time)
|
||||
struct ecb *ecb;
|
||||
int time;
|
||||
|
||||
ahb_timeout(struct ecb *ecb)
|
||||
{
|
||||
int timeprev;
|
||||
struct ecb *prev;
|
||||
int s = splbio();
|
||||
|
||||
if(prev = ahb_latest) /* yes, an assign */
|
||||
{
|
||||
timeprev = ahb_furtherest;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeprev = 0;
|
||||
}
|
||||
while(prev && (timeprev > time))
|
||||
{
|
||||
timeprev -= prev->delta;
|
||||
prev = prev->sooner;
|
||||
}
|
||||
if(prev)
|
||||
{
|
||||
ecb->delta = time - timeprev;
|
||||
if( ecb->later = prev->later) /* yes an assign */
|
||||
{
|
||||
ecb->later->sooner = ecb;
|
||||
ecb->later->delta -= ecb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_furtherest = time;
|
||||
ahb_latest = ecb;
|
||||
}
|
||||
ecb->sooner = prev;
|
||||
prev->later = ecb;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ecb->later = ahb_soonest) /* yes, an assign*/
|
||||
{
|
||||
ecb->later->sooner = ecb;
|
||||
ecb->later->delta -= time;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_furtherest = time;
|
||||
ahb_latest = ecb;
|
||||
}
|
||||
ecb->delta = time;
|
||||
ecb->sooner = (struct ecb *)0;
|
||||
ahb_soonest = ecb;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
ahb_remove_timeout(ecb)
|
||||
struct ecb *ecb;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
if(ecb->sooner)
|
||||
{
|
||||
ecb->sooner->later = ecb->later;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_soonest = ecb->later;
|
||||
}
|
||||
if(ecb->later)
|
||||
{
|
||||
ecb->later->sooner = ecb->sooner;
|
||||
ecb->later->delta += ecb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_latest = ecb->sooner;
|
||||
ahb_furtherest -= ecb->delta;
|
||||
}
|
||||
ecb->sooner = ecb->later = (struct ecb *)0;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
extern int hz;
|
||||
#define ONETICK 500 /* milliseconds */
|
||||
#define SLEEPTIME ((hz * ONETICK) / 1000)
|
||||
ahb_timeout(arg)
|
||||
int arg;
|
||||
{
|
||||
struct ecb *ecb;
|
||||
int unit;
|
||||
int s = splbio();
|
||||
|
||||
while( ecb = ahb_soonest )
|
||||
unit = ecb->xs->adapter;
|
||||
printf("ahb%d:%d device timed out\n",unit
|
||||
,ecb->xs->targ);
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
ahb_print_active_ecb(unit);
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
/***************************************\
|
||||
* If it's immediate, don't try abort it *
|
||||
\***************************************/
|
||||
if(ecb->flags & ECB_IMMED)
|
||||
{
|
||||
if(ecb->delta <= ONETICK)
|
||||
/***********************************************\
|
||||
* It has timed out, we need to do some work *
|
||||
\***********************************************/
|
||||
{
|
||||
unit = ecb->xs->adapter;
|
||||
printf("ahb%d:%d device timed out\n",unit
|
||||
,ecb->xs->targ);
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
ahb_print_active_ecb();
|
||||
|
||||
/***************************************\
|
||||
* Unlink it from the queue *
|
||||
\***************************************/
|
||||
ahb_remove_timeout(ecb);
|
||||
|
||||
/***************************************\
|
||||
* If it's immediate, don't try abort it *
|
||||
\***************************************/
|
||||
if(ecb->flags & ECB_IMMED)
|
||||
{
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->flags |= ECB_IMMED_FAIL;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
continue;
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ecb->flags == ECB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("AGAIN");
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
|
||||
/* 2 secs for the abort */
|
||||
ahb_add_timeout(ecb,2000 + ONETICK);
|
||||
ecb->flags = ECB_ABORTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/***********************************************\
|
||||
* It has not timed out, adjust and leave *
|
||||
\***********************************************/
|
||||
{
|
||||
ecb->delta -= ONETICK;
|
||||
ahb_furtherest -= ONETICK;
|
||||
break;
|
||||
}
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->flags |= ECB_IMMED_FAIL;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ecb->flags == ECB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("AGAIN");
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
|
||||
/* 2 secs for the abort */
|
||||
timeout(ahb_timeout,ecb,2 * hz);
|
||||
ecb->flags = ECB_ABORTED;
|
||||
}
|
||||
splx(s);
|
||||
timeout(ahb_timeout,arg,SLEEPTIME);
|
||||
}
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
ahb_show_scsi_cmd(struct scsi_xfer *xs)
|
||||
{
|
||||
u_char *b = (u_char *)xs->cmd;
|
||||
|
|
@ -1419,24 +1309,26 @@ struct ecb *ecb;
|
|||
,ecb->opcode
|
||||
,ecb->cdblen
|
||||
,ecb->senselen);
|
||||
printf(" datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
|
||||
printf(" datlen:%d hstat:%x tstat:%x flags:%x\n"
|
||||
,ecb->datalen
|
||||
,ecb->ecb_status.ha_status
|
||||
,ecb->ecb_status.targ_status
|
||||
,ecb->delta
|
||||
,ecb->flags);
|
||||
ahb_show_scsi_cmd(ecb->xs);
|
||||
}
|
||||
|
||||
ahb_print_active_ecb()
|
||||
ahb_print_active_ecb(int unit)
|
||||
{
|
||||
struct ecb *ecb;
|
||||
ecb = ahb_soonest;
|
||||
struct ecb *ecb = ahb_data[unit].ecbs;
|
||||
int i = NUM_CONCURRENT;
|
||||
|
||||
while(ecb)
|
||||
while(i--)
|
||||
{
|
||||
ahb_print_ecb(ecb);
|
||||
ecb = ecb->later;
|
||||
if(ecb->flags != ECB_FREE)
|
||||
{
|
||||
ahb_print_ecb(ecb);
|
||||
}
|
||||
ecb++;
|
||||
}
|
||||
printf("Furtherest = %d\n",ahb_furtherest);
|
||||
}
|
||||
#endif /*AHBDEBUG */
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@
|
|||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*
|
||||
*
|
||||
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
|
||||
* -------------------- ----- ----------------------
|
||||
* CURRENT PATCH LEVEL: 1 00098
|
||||
* -------------------- ----- ----------------------
|
||||
*
|
||||
* 16 Feb 93 Julian Elischer ADDED for SCSI system
|
||||
*/
|
||||
|
||||
/*
|
||||
|
|
@ -20,34 +27,17 @@
|
|||
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log: aha1542.c,v $
|
||||
* Revision 1.4 1993/08/06 11:58:59 rgrimes
|
||||
* Fixed **probing for scsi devices** message to have a controller and unit
|
||||
* message on the begining of it:
|
||||
* aha0: **probing for scsi devices**
|
||||
*
|
||||
* Revision 1.3 1993/07/29 11:55:31 nate
|
||||
* Syncing our sources back with Julian's, and removing PATCHKIT headers.
|
||||
*
|
||||
* Large Bustek changes, most everything else is minimal.
|
||||
*
|
||||
* Revision 1.2 1993/07/15 17:52:58 davidg
|
||||
* Modified attach printf's so that the output is compatible with the "new"
|
||||
* way of doing things. There still remain several drivers that need to
|
||||
* be updated. Also added a compile-time option to pccons to switch the
|
||||
* control and caps-lock keys (REVERSE_CAPS_CTRL) - added for my personal
|
||||
* sanity.
|
||||
*
|
||||
* Revision 1.1.1.1 1993/06/12 14:57:59 rgrimes
|
||||
* Initial import, 0.1 + pk 0.2.4-B1
|
||||
*
|
||||
* Revision 1.3 93/05/22 16:51:18 julian
|
||||
* $Log: aha1542.c,v $
|
||||
* Revision 1.4 93/08/07 13:17:25 julian
|
||||
* replaced private timeout stuff with system timeout calls
|
||||
*
|
||||
* Revision 1.3 93/05/22 16:51:18 root
|
||||
* set up dev->dev_pic before it's needed for OSF
|
||||
*
|
||||
* Revision 1.2 93/05/07 11:40:27 julian
|
||||
* Revision 1.2 93/05/07 11:40:27 root
|
||||
* fixed SLEEPTIME calculation
|
||||
*
|
||||
* Revision 1.1 93/05/07 11:14:03 julian
|
||||
* Revision 1.1 93/05/07 11:14:03 root
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 1.6 1992/08/24 21:01:58 jason
|
||||
|
|
@ -148,6 +138,7 @@ int Debugger();
|
|||
#define Debugger() panic("should call debugger here (adaptec.c)")
|
||||
#endif NDDB
|
||||
#endif __386BSD__
|
||||
extern int hz;
|
||||
extern int delaycount; /* from clock setup code */
|
||||
|
||||
/************************** board definitions *******************************/
|
||||
|
|
@ -280,8 +271,6 @@ struct aha_ccb {
|
|||
struct aha_ccb *next;
|
||||
struct scsi_xfer *xfer; /* the scsi_xfer for this cmd */
|
||||
struct aha_mbx_out *mbx; /* pointer to mail box */
|
||||
long int delta; /* difference from previous*/
|
||||
struct aha_ccb *later,*sooner;
|
||||
int flags;
|
||||
#define CCB_FREE 0
|
||||
#define CCB_ACTIVE 1
|
||||
|
|
@ -289,9 +278,6 @@ struct aha_ccb {
|
|||
|
||||
};
|
||||
|
||||
struct aha_ccb *aha_soonest = (struct aha_ccb *)0;
|
||||
struct aha_ccb *aha_latest = (struct aha_ccb *)0;
|
||||
long int aha_furtherest = 0; /* longest time in the timeout queue */
|
||||
|
||||
/*
|
||||
* opcode fields
|
||||
|
|
@ -403,7 +389,9 @@ int aha_initialized[NAHA];
|
|||
#ifdef OSF
|
||||
int aha_attached[NAHA];
|
||||
#endif OSF
|
||||
int aha_debug = 0;
|
||||
#ifdef AHADEBUG
|
||||
int aha_debug = 1;
|
||||
#endif /*AHADEBUG*/
|
||||
|
||||
int ahaprobe(), ahaattach(), ahaintr();
|
||||
#ifdef MACH
|
||||
|
|
@ -643,6 +631,7 @@ struct isa_dev *dev;
|
|||
panic("Unable to add aha interrupt handler");
|
||||
#endif /* !defined(OSF) */
|
||||
#ifdef __386BSD__
|
||||
printf("\n **");
|
||||
#else __386BSD__
|
||||
printf("port=%x spl=%d\n",
|
||||
dev->dev_addr, dev->dev_spl);
|
||||
|
|
@ -660,7 +649,7 @@ struct isa_dev *dev;
|
|||
int unit = dev->dev_unit;
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("aha%d: **probing for scsi devices**\n", unit);
|
||||
printf(" probing for scsi devices**\n");
|
||||
#endif __386BSD__
|
||||
/***********************************************\
|
||||
* ask the adapter what subunits are present *
|
||||
|
|
@ -669,10 +658,9 @@ struct isa_dev *dev;
|
|||
#if defined(OSF)
|
||||
aha_attached[unit]=1;
|
||||
#endif /* defined(OSF) */
|
||||
if(!unit) /* only one for all boards */
|
||||
{
|
||||
aha_timeout(0);
|
||||
}
|
||||
#ifdef __386BSD__
|
||||
printf("aha%d",unit);
|
||||
#endif __386BSD__
|
||||
return;
|
||||
|
||||
}
|
||||
|
|
@ -697,8 +685,10 @@ ahaintr(unit)
|
|||
unsigned char stat;
|
||||
register i;
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ahaintr ");
|
||||
#endif /*AHADEBUG*/
|
||||
/***********************************************\
|
||||
* First acknowlege the interrupt, Then if it's *
|
||||
* not telling about a completed operation *
|
||||
|
|
@ -706,12 +696,16 @@ ahaintr(unit)
|
|||
\***********************************************/
|
||||
stat = inb(AHA_INTR_PORT);
|
||||
outb(AHA_CTRL_STAT_PORT, AHA_IRST);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("int ");
|
||||
#endif /*AHADEBUG*/
|
||||
if (! (stat & AHA_MBIF))
|
||||
return(1);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("b ");
|
||||
#endif /*AHADEBUG*/
|
||||
#if defined(OSF)
|
||||
if (!aha_attached[unit])
|
||||
{
|
||||
|
|
@ -733,15 +727,19 @@ ahaintr(unit)
|
|||
switch(stat)
|
||||
{
|
||||
case AHA_MBI_ABORT:
|
||||
#ifdef AHADEBUG
|
||||
if(aha_debug)
|
||||
printf("abort");
|
||||
#endif /*AHADEBUG*/
|
||||
ccb->host_stat = AHA_ABORTED;
|
||||
break;
|
||||
|
||||
case AHA_MBI_UNKNOWN:
|
||||
ccb = (struct aha_ccb *)0;
|
||||
#ifdef AHADEBUG
|
||||
if(aha_debug)
|
||||
printf("unknown ccb for abort ");
|
||||
#endif /*AHADEBUG*/
|
||||
/* may have missed it */
|
||||
/* no such ccb known for abort */
|
||||
|
||||
|
|
@ -752,6 +750,7 @@ ahaintr(unit)
|
|||
panic("Impossible mbxi status");
|
||||
|
||||
}
|
||||
#ifdef AHADEBUG
|
||||
if( aha_debug && ccb )
|
||||
{
|
||||
u_char *cp;
|
||||
|
|
@ -763,10 +762,11 @@ ahaintr(unit)
|
|||
, aha_mbx[unit].mbi[i].stat, i);
|
||||
printf("addr = 0x%x\n", ccb);
|
||||
}
|
||||
#endif /*AHADEBUG*/
|
||||
}
|
||||
if(ccb)
|
||||
{
|
||||
aha_remove_timeout(ccb);
|
||||
untimeout(aha_timeout,ccb);
|
||||
aha_done(unit,ccb);
|
||||
}
|
||||
aha_mbx[unit].mbi[i].stat = AHA_MBI_FREE;
|
||||
|
|
@ -784,19 +784,16 @@ struct aha_ccb *ccb;
|
|||
{
|
||||
unsigned int opri;
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ccb%d(0x%x)> ",unit,flags);
|
||||
#endif /*AHADEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
|
||||
ccb->next = aha_ccb_free[unit];
|
||||
aha_ccb_free[unit] = ccb;
|
||||
ccb->flags = CCB_FREE;
|
||||
if(ccb->sooner || ccb->later)
|
||||
{
|
||||
printf("yikes, still in timeout queue\n");
|
||||
aha_remove_timeout(ccb);
|
||||
}
|
||||
/***********************************************\
|
||||
* If there were none, wake abybody waiting for *
|
||||
* one to come free, starting with queued entries*
|
||||
|
|
@ -817,8 +814,10 @@ aha_get_ccb(unit,flags)
|
|||
unsigned opri;
|
||||
struct aha_ccb *rc;
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("<ccb%d(0x%x) ",unit,flags);
|
||||
#endif /*AHADEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
/***********************************************\
|
||||
|
|
@ -851,8 +850,10 @@ struct aha_ccb *ccb;
|
|||
struct scsi_sense_data *s1,*s2;
|
||||
struct scsi_xfer *xs = ccb->xfer;
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES )
|
||||
printf("aha_done ");
|
||||
#endif /*AHADEBUG*/
|
||||
/***********************************************\
|
||||
* Otherwise, put the results of the operation *
|
||||
* into the xfer and call whoever started it *
|
||||
|
|
@ -880,11 +881,13 @@ struct aha_ccb *ccb;
|
|||
break;
|
||||
default: /* Other scsi protocol messes */
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
#ifdef AHADEBUG
|
||||
if (aha_debug > 1)
|
||||
{
|
||||
printf("host_stat%x\n",
|
||||
ccb->host_stat);
|
||||
}
|
||||
#endif /*AHADEBUG*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -901,11 +904,13 @@ struct aha_ccb *ccb;
|
|||
xs->error = XS_BUSY;
|
||||
break;
|
||||
default:
|
||||
#ifdef AHADEBUG
|
||||
if (aha_debug > 1)
|
||||
{
|
||||
printf("target_stat%x\n",
|
||||
ccb->target_stat);
|
||||
}
|
||||
#endif /*AHADEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
|
|
@ -946,8 +951,10 @@ int unit;
|
|||
}
|
||||
if (i >= AHA_RESET_TIMEOUT)
|
||||
{
|
||||
#ifdef AHADEBUG
|
||||
if (aha_debug)
|
||||
printf("aha_init: No answer from adaptec board\n");
|
||||
#endif /*AHADEBUG*/
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
|
|
@ -957,12 +964,12 @@ int unit;
|
|||
* level *
|
||||
\***********************************************/
|
||||
#ifdef __386BSD__
|
||||
printf("aha%d reading board settings, ",unit);
|
||||
#define PRNT(x)
|
||||
#else __386BSD__
|
||||
printf("aha%d:",unit);
|
||||
#define PRNT(x) printf(x)
|
||||
#endif __386BSD__
|
||||
DELAY(1000); /* for Bustek 545 */
|
||||
aha_cmd(unit,0, sizeof(conf), 0 ,&conf, AHA_CONF_GET);
|
||||
switch(conf.chan)
|
||||
{
|
||||
|
|
@ -1110,8 +1117,10 @@ struct scsi_xfer *xs;
|
|||
struct iovec *iovp;
|
||||
int s;
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("aha_scsi_cmd ");
|
||||
#endif /*AHADEBUG*/
|
||||
/***********************************************\
|
||||
* get a ccb (mbox-out) to use. If the transfer *
|
||||
* is from a buf (possibly from interrupt time) *
|
||||
|
|
@ -1175,10 +1184,12 @@ struct scsi_xfer *xs;
|
|||
{
|
||||
lto3b(iovp->iov_base,&(sg->seg_addr));
|
||||
lto3b(iovp->iov_len,&(sg->seg_len));
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x@0x%x)"
|
||||
,iovp->iov_len
|
||||
,iovp->iov_base);
|
||||
#endif /*AHADEBUG*/
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
|
|
@ -1191,8 +1202,10 @@ struct scsi_xfer *xs;
|
|||
* Set up the scatter gather block *
|
||||
\***********************************************/
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("%d @0x%x:- ",xs->datalen,xs->data);
|
||||
#endif /*AHADEBUG*/
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
|
@ -1204,8 +1217,10 @@ struct scsi_xfer *xs;
|
|||
/* put in the base address */
|
||||
lto3b(thisphys,&(sg->seg_addr));
|
||||
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("0x%x",thisphys);
|
||||
#endif /*AHADEBUG*/
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
|
|
@ -1235,16 +1250,20 @@ struct scsi_xfer *xs;
|
|||
/***************************************\
|
||||
* next page isn't contiguous, finish the seg*
|
||||
\***************************************/
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x)",bytes_this_seg);
|
||||
#endif /*AHADEBUG*/
|
||||
lto3b(bytes_this_seg,&(sg->seg_len));
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
}
|
||||
lto3b(seg * sizeof(struct aha_scat_gath),ccb->data_length);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("\n");
|
||||
#endif /*AHADEBUG*/
|
||||
if (datalen)
|
||||
{ /* there's still data, must have run out of segs! */
|
||||
printf("aha_scsi_cmd%d: more than %d DMA segs\n",
|
||||
|
|
@ -1266,6 +1285,7 @@ struct scsi_xfer *xs;
|
|||
\***********************************************/
|
||||
if(!(flags & SCSI_RESET))
|
||||
bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & SHOWCOMMANDS)
|
||||
{
|
||||
u_char *b = (u_char *)&ccb->scsi_cmd;
|
||||
|
|
@ -1291,22 +1311,27 @@ struct scsi_xfer *xs;
|
|||
);
|
||||
}
|
||||
}
|
||||
#endif /*AHADEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
{
|
||||
s= splbio(); /* stop instant timeouts */
|
||||
aha_add_timeout(ccb,xs->timeout);
|
||||
timeout(aha_timeout,ccb,(xs->timeout * hz) / 1000);
|
||||
aha_startmbx(ccb->mbx);
|
||||
/***********************************************\
|
||||
* Usually return SUCCESSFULLY QUEUED *
|
||||
\***********************************************/
|
||||
splx(s);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("sent ");
|
||||
#endif /*AHADEBUG*/
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
aha_startmbx(ccb->mbx);
|
||||
#ifdef AHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_sent, waiting ");
|
||||
#endif /*AHADEBUG*/
|
||||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
|
|
@ -1406,21 +1431,21 @@ int unit;
|
|||
{
|
||||
speed++;
|
||||
}
|
||||
/* XXX printf("%d nSEC ok, use ",retval); */
|
||||
printf("%d nSEC ok, use ",retval);
|
||||
retval2 = aha_bus_speed_check(unit,speed);
|
||||
if(retval2 == HAD_ERROR) /* retval is slowest already */
|
||||
{
|
||||
/* XXX printf("marginal "); */
|
||||
printf("marginal ");
|
||||
retval2 = retval;
|
||||
}
|
||||
if(retval2)
|
||||
{
|
||||
/* XXX printf("%d nSEC ",retval2); */
|
||||
printf("%d nSEC ",retval2);
|
||||
return(retval2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* XXX printf(".. slower failed, abort.\n",retval); */
|
||||
printf(".. slower failed, abort.\n",retval);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
@ -1498,166 +1523,45 @@ int unit,speed;
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* +----------+ +----------+ +----------+
|
||||
* aha_soonest--->| later |--->| later|--->| later|-->0
|
||||
* | [Delta] | | [Delta] | | [Delta] |
|
||||
* 0<---|sooner |<---|sooner |<---|sooner |<---aha_latest
|
||||
* +----------+ +----------+ +----------+
|
||||
*
|
||||
* aha_furtherest = sum(Delta[1..n])
|
||||
*/
|
||||
aha_add_timeout(ccb,time)
|
||||
struct aha_ccb *ccb;
|
||||
int time;
|
||||
|
||||
aha_timeout(struct aha_ccb *ccb)
|
||||
{
|
||||
int timeprev;
|
||||
struct aha_ccb *prev;
|
||||
int s = splbio();
|
||||
|
||||
if(prev = aha_latest) /* yes, an assign */
|
||||
{
|
||||
timeprev = aha_furtherest;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeprev = 0;
|
||||
}
|
||||
while(prev && (timeprev > time))
|
||||
{
|
||||
timeprev -= prev->delta;
|
||||
prev = prev->sooner;
|
||||
}
|
||||
if(prev)
|
||||
{
|
||||
ccb->delta = time - timeprev;
|
||||
if( ccb->later = prev->later) /* yes an assign */
|
||||
{
|
||||
ccb->later->sooner = ccb;
|
||||
ccb->later->delta -= ccb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
aha_furtherest = time;
|
||||
aha_latest = ccb;
|
||||
}
|
||||
ccb->sooner = prev;
|
||||
prev->later = ccb;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ccb->later = aha_soonest) /* yes, an assign*/
|
||||
{
|
||||
ccb->later->sooner = ccb;
|
||||
ccb->later->delta -= time;
|
||||
}
|
||||
else
|
||||
{
|
||||
aha_furtherest = time;
|
||||
aha_latest = ccb;
|
||||
}
|
||||
ccb->delta = time;
|
||||
ccb->sooner = (struct aha_ccb *)0;
|
||||
aha_soonest = ccb;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
aha_remove_timeout(ccb)
|
||||
struct aha_ccb *ccb;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
if(ccb->sooner)
|
||||
{
|
||||
ccb->sooner->later = ccb->later;
|
||||
}
|
||||
else
|
||||
{
|
||||
aha_soonest = ccb->later;
|
||||
}
|
||||
if(ccb->later)
|
||||
{
|
||||
ccb->later->sooner = ccb->sooner;
|
||||
ccb->later->delta += ccb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
aha_latest = ccb->sooner;
|
||||
aha_furtherest -= ccb->delta;
|
||||
}
|
||||
ccb->sooner = ccb->later = (struct aha_ccb *)0;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
extern int hz;
|
||||
#define ONETICK 500 /* milliseconds */
|
||||
#define SLEEPTIME ((hz * ONETICK) / 1000)
|
||||
aha_timeout(arg)
|
||||
int arg;
|
||||
{
|
||||
struct aha_ccb *ccb;
|
||||
int unit;
|
||||
int s = splbio();
|
||||
|
||||
while( ccb = aha_soonest )
|
||||
unit = ccb->xfer->adapter;
|
||||
printf("aha%d: device %d timed out ",unit
|
||||
,ccb->xfer->targ);
|
||||
|
||||
/***************************************\
|
||||
* If The ccb's mbx is not free, then *
|
||||
* the board has gone south *
|
||||
\***************************************/
|
||||
if(ccb->mbx->cmd != AHA_MBO_FREE)
|
||||
{
|
||||
if(ccb->delta <= ONETICK)
|
||||
/***********************************************\
|
||||
* It has timed out, we need to do some work *
|
||||
\***********************************************/
|
||||
{
|
||||
unit = ccb->xfer->adapter;
|
||||
printf("aha%d: device %d timed out ",unit
|
||||
,ccb->xfer->targ);
|
||||
|
||||
/***************************************\
|
||||
* Unlink it from the queue *
|
||||
\***************************************/
|
||||
aha_remove_timeout(ccb);
|
||||
|
||||
/***************************************\
|
||||
* If The ccb's mbx is not free, then *
|
||||
* the board has gone south *
|
||||
\***************************************/
|
||||
if(ccb->mbx->cmd != AHA_MBO_FREE)
|
||||
{
|
||||
printf("aha%d not taking commands!\n"
|
||||
,unit);
|
||||
Debugger();
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ccb->flags == CCB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf(" AGAIN\n");
|
||||
ccb->xfer->retries = 0; /* I MEAN IT ! */
|
||||
ccb->host_stat = AHA_ABORTED;
|
||||
aha_done(unit,ccb);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
aha_abortmbx(ccb->mbx);
|
||||
/* 2 secs for the abort */
|
||||
aha_add_timeout(ccb,2000 + ONETICK);
|
||||
ccb->flags = CCB_ABORTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/***********************************************\
|
||||
* It has not timed out, adjust and leave *
|
||||
\***********************************************/
|
||||
{
|
||||
ccb->delta -= ONETICK;
|
||||
aha_furtherest -= ONETICK;
|
||||
break;
|
||||
}
|
||||
printf("aha%d not taking commands!\n"
|
||||
,unit);
|
||||
Debugger();
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ccb->flags == CCB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf(" AGAIN\n");
|
||||
ccb->xfer->retries = 0; /* I MEAN IT ! */
|
||||
ccb->host_stat = AHA_ABORTED;
|
||||
aha_done(unit,ccb);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
aha_abortmbx(ccb->mbx);
|
||||
/* 2 secs for the abort */
|
||||
timeout(aha_timeout,ccb,2 * hz);
|
||||
ccb->flags = CCB_ABORTED;
|
||||
}
|
||||
splx(s);
|
||||
timeout(aha_timeout,arg,SLEEPTIME);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,41 +11,15 @@
|
|||
* TFS supplies this software to be publicly redistributed
|
||||
* on the understanding that TFS is not responsible for the correct
|
||||
* functioning of this software in any circumstances.
|
||||
*/
|
||||
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log: aha1742.c,v $
|
||||
* Revision 1.4 1993/08/06 11:59:02 rgrimes
|
||||
* Fixed **probing for scsi devices** message to have a controller and unit
|
||||
* message on the begining of it:
|
||||
* aha0: **probing for scsi devices**
|
||||
*
|
||||
* Revision 1.3 1993/07/29 11:55:34 nate
|
||||
* Syncing our sources back with Julian's, and removing PATCHKIT headers.
|
||||
*
|
||||
* Large Bustek changes, most everything else is minimal.
|
||||
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
|
||||
* -------------------- ----- ----------------------
|
||||
* CURRENT PATCH LEVEL: 1 00098
|
||||
* -------------------- ----- ----------------------
|
||||
*
|
||||
* Revision 1.2 1993/07/15 17:52:58 davidg
|
||||
* Modified attach printf's so that the output is compatible with the "new"
|
||||
* way of doing things. There still remain several drivers that need to
|
||||
* be updated. Also added a compile-time option to pccons to switch the
|
||||
* control and caps-lock keys (REVERSE_CAPS_CTRL) - added for my personal
|
||||
* sanity.
|
||||
*
|
||||
* Revision 1.1.1.1 1993/06/12 14:57:59 rgrimes
|
||||
* Initial import, 0.1 + pk 0.2.4-B1
|
||||
*
|
||||
* julian - removed un-necessary splx() calls and debugging code
|
||||
*
|
||||
* Revision 1.3 93/05/22 16:51:18 julian
|
||||
* set up dev->dev_pic before it's needed for OSF
|
||||
*
|
||||
* Revision 1.2 93/05/07 11:40:27 julian
|
||||
* fixed SLEEPTIME calculation
|
||||
*
|
||||
* Revision 1.1 93/05/07 11:14:03 julian
|
||||
* Initial revision
|
||||
* 16 Feb 93 Julian Elischer ADDED for SCSI system
|
||||
* commenced: Sun Sep 27 18:14:01 PDT 1992
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
|
@ -103,6 +77,7 @@ int Debugger();
|
|||
#endif MACH
|
||||
|
||||
typedef unsigned long int physaddr;
|
||||
extern int hz;
|
||||
|
||||
#ifdef MACH
|
||||
extern physaddr kvtophys();
|
||||
|
|
@ -297,8 +272,6 @@ struct ecb
|
|||
/*-----------------end of hardware supported fields----------------*/
|
||||
struct ecb *next; /* in free list */
|
||||
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
|
||||
long int delta; /* difference from previous*/
|
||||
struct ecb *later,*sooner;
|
||||
int flags;
|
||||
#define ECB_FREE 0
|
||||
#define ECB_ACTIVE 1
|
||||
|
|
@ -310,9 +283,6 @@ struct ecb
|
|||
struct scsi_sense_data ecb_sense;
|
||||
};
|
||||
|
||||
struct ecb *ahb_soonest = (struct ecb *)0;
|
||||
struct ecb *ahb_latest = (struct ecb *)0;
|
||||
long int ahb_furtherest = 0; /* longest time in the timeout queue */
|
||||
/**/
|
||||
|
||||
struct ahb_data
|
||||
|
|
@ -546,6 +516,7 @@ struct isa_dev *dev;
|
|||
#ifdef __386BSD__ /* 386BSD */
|
||||
dev->id_irq = (1 << ahb_data[unit].vect);
|
||||
dev->id_drq = -1; /* use EISA dma */
|
||||
printf("\n **");
|
||||
#endif __386BSD__
|
||||
|
||||
ahb_unit++;
|
||||
|
|
@ -562,7 +533,7 @@ struct isa_dev *dev;
|
|||
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d: **probing for scsi devices**\n", unit);
|
||||
printf(" probing for scsi devices**\n");
|
||||
#endif __386BSD__
|
||||
|
||||
/***********************************************\
|
||||
|
|
@ -572,10 +543,9 @@ struct isa_dev *dev;
|
|||
#if defined(OSF)
|
||||
ahb_attached[unit]=1;
|
||||
#endif /* defined(OSF) */
|
||||
if(!unit) /* only one for all boards */
|
||||
{
|
||||
ahb_timeout(0);
|
||||
}
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d",unit);
|
||||
#endif __386BSD__
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -603,8 +573,10 @@ ahbintr(unit)
|
|||
|
||||
int port = ahb_data[unit].baseport;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ahbintr ");
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
#if defined(OSF)
|
||||
if (!ahb_attached[unit])
|
||||
|
|
@ -623,8 +595,10 @@ ahbintr(unit)
|
|||
stat = ahbstat & G2INTST_INT_STAT;
|
||||
mboxval = inl(port + MBOXIN0);/* don't know this will work */
|
||||
outb(port + G2CNTRL, G2CNTRL_CLEAR_EISA_INT);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("status = 0x%x ",stat);
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* Process the completed operation *
|
||||
\***********************************************/
|
||||
|
|
@ -647,13 +621,9 @@ ahbintr(unit)
|
|||
ahb_data[unit].immed_ecb = 0;
|
||||
break;
|
||||
case AHB_ASN: /* for target mode */
|
||||
printf("ahb%d: Unexpected ASN interrupt(%x)\n",
|
||||
unit, mboxval);
|
||||
ecb = 0;
|
||||
break;
|
||||
case AHB_HW_ERR:
|
||||
printf("ahb%d: Hardware error interrupt(%x)\n",
|
||||
unit, mboxval);
|
||||
ecb = 0;
|
||||
break;
|
||||
case AHB_ECB_RECOVERED:
|
||||
|
|
@ -669,13 +639,15 @@ ahbintr(unit)
|
|||
}
|
||||
if(ecb)
|
||||
{
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWCMDS )
|
||||
{
|
||||
ahb_show_scsi_cmd(ecb->xs);
|
||||
}
|
||||
if((ahb_debug & AHB_SHOWECBS) && ecb)
|
||||
printf("<int ecb(%x)>",ecb);
|
||||
ahb_remove_timeout(ecb);
|
||||
#endif /*AHBDEBUG*/
|
||||
untimeout(ahb_timeout,ecb);
|
||||
ahb_done(unit,ecb,((stat == AHB_ECB_OK)?SUCCESS:FAIL));
|
||||
}
|
||||
}
|
||||
|
|
@ -695,8 +667,10 @@ struct ecb *ecb;
|
|||
struct scsi_sense_data *s1,*s2;
|
||||
struct scsi_xfer *xs = ecb->xs;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
|
||||
printf("ahb_done ");
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* Otherwise, put the results of the operation *
|
||||
* into the xfer and call whoever started it *
|
||||
|
|
@ -732,19 +706,23 @@ struct ecb *ecb;
|
|||
case HS_CMD_ABORTED_ADAPTER: /* No response */
|
||||
break;
|
||||
case HS_TIMED_OUT: /* No response */
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("timeout reported back\n");
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
xs->error = XS_TIMEOUT;
|
||||
break;
|
||||
default: /* Other scsi protocol messes */
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("unexpected ha_status: %x\n",
|
||||
stat->ha_status);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -761,11 +739,13 @@ struct ecb *ecb;
|
|||
xs->error = XS_BUSY;
|
||||
break;
|
||||
default:
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
{
|
||||
printf("unexpected targ_status: %x\n",
|
||||
stat->targ_status);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
|
|
@ -785,8 +765,10 @@ struct ecb *ecb;
|
|||
{
|
||||
unsigned int opri;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ecb%d(0x%x)> ",unit,flags);
|
||||
#endif /*AHBDEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
|
||||
|
|
@ -813,8 +795,10 @@ ahb_get_ecb(unit,flags)
|
|||
unsigned opri;
|
||||
struct ecb *rc;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("<ecb%d(0x%x) ",unit,flags);
|
||||
#endif /*AHBDEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
/***********************************************\
|
||||
|
|
@ -865,8 +849,10 @@ int unit;
|
|||
&& (spincount--));
|
||||
if(spincount == -1)
|
||||
{
|
||||
#ifdef AHBDEBUG
|
||||
if (ahb_debug & AHB_SHOWMISC)
|
||||
printf("ahb_init: No answer from bt742a board\n");
|
||||
#endif /*AHBDEBUG*/
|
||||
return(ENXIO);
|
||||
}
|
||||
i = inb(port + MBOXIN0) & 0xff;
|
||||
|
|
@ -890,6 +876,7 @@ int unit;
|
|||
* level *
|
||||
\***********************************************/
|
||||
#ifdef __386BSD__
|
||||
printf("ahb%d reading board settings, ",unit);
|
||||
#define PRNT(x)
|
||||
#else __386BSD__
|
||||
printf("ahb%d:",unit);
|
||||
|
|
@ -988,8 +975,10 @@ struct scsi_xfer *xs;
|
|||
int bytes_this_seg,bytes_this_page,datalen,flags;
|
||||
struct iovec *iovp;
|
||||
int s;
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("ahb_scsi_cmd ");
|
||||
#endif /*AHBDEBUG*/
|
||||
/***********************************************\
|
||||
* get a ecb (mbox-out) to use. If the transfer *
|
||||
* is from a buf (possibly from interrupt time) *
|
||||
|
|
@ -1014,12 +1003,14 @@ struct scsi_xfer *xs;
|
|||
}
|
||||
|
||||
cheat = ecb;
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
printf("<start ecb(%x)>",ecb);
|
||||
if(scsi_debug & SHOWCOMMANDS)
|
||||
{
|
||||
ahb_show_scsi_cmd(xs);
|
||||
}
|
||||
#endif /*AHBDEBUG*/
|
||||
ecb->xs = xs;
|
||||
/***********************************************\
|
||||
* If it's a reset, we need to do an 'immediate' *
|
||||
|
|
@ -1039,7 +1030,7 @@ cheat = ecb;
|
|||
{
|
||||
s = splbio();
|
||||
ahb_send_immed(unit,xs->targ,AHB_TARG_RESET);
|
||||
ahb_add_timeout(ecb,xs->timeout);
|
||||
timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
|
||||
splx(s);
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
|
|
@ -1049,8 +1040,10 @@ cheat = ecb;
|
|||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("wait ");
|
||||
#endif /*AHBDEBUG*/
|
||||
if( ahb_poll(unit,xs->timeout))
|
||||
{
|
||||
ahb_free_ecb(unit,ecb,flags);
|
||||
|
|
@ -1089,10 +1082,12 @@ cheat = ecb;
|
|||
{
|
||||
sg->addr = (physaddr)iovp->iov_base;
|
||||
xs->datalen += sg->len = iovp->iov_len;
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x@0x%x)"
|
||||
,iovp->iov_len
|
||||
,iovp->iov_base);
|
||||
#endif /*AHBDEBUG*/
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
|
|
@ -1105,8 +1100,10 @@ cheat = ecb;
|
|||
* Set up the scatter gather block *
|
||||
\***********************************************/
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("%d @0x%x:- ",xs->datalen,xs->data);
|
||||
#endif /*AHBDEBUG*/
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
|
@ -1118,8 +1115,10 @@ cheat = ecb;
|
|||
/* put in the base address */
|
||||
sg->addr = thisphys;
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("0x%x",thisphys);
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
|
|
@ -1148,16 +1147,20 @@ cheat = ecb;
|
|||
/********************************************\
|
||||
* next page isn't contiguous, finish the seg *
|
||||
\********************************************/
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x)",bytes_this_seg);
|
||||
#endif /*AHBDEBUG*/
|
||||
sg->len = bytes_this_seg;
|
||||
sg++;
|
||||
seg++;
|
||||
}
|
||||
} /*end of iov/kv decision */
|
||||
ecb->datalen = seg * sizeof(struct ahb_dma_seg);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("\n");
|
||||
#endif /*AHBDEBUG*/
|
||||
if (datalen)
|
||||
{ /* there's still data, must have run out of segs! */
|
||||
printf("ahb_scsi_cmd%d: more than %d DMA segs\n",
|
||||
|
|
@ -1185,18 +1188,22 @@ cheat = ecb;
|
|||
{
|
||||
s = splbio();
|
||||
ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
|
||||
ahb_add_timeout(ecb,xs->timeout);
|
||||
timeout(ahb_timeout,ecb,(xs->timeout * hz)/1000);
|
||||
splx(s);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_sent ");
|
||||
#endif /*AHBDEBUG*/
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
ahb_send_mbox(unit,OP_START_ECB,xs->targ,ecb);
|
||||
#ifdef AHBDEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_wait ");
|
||||
#endif /*AHBDEBUG*/
|
||||
do
|
||||
{
|
||||
if(ahb_poll(unit,xs->timeout))
|
||||
|
|
@ -1219,172 +1226,55 @@ cheat = ecb;
|
|||
return(COMPLETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* +----------+ +----------+ +----------+
|
||||
* ahb_soonest--->| later |--->| later|--->| later|--->0
|
||||
* | [Delta] | | [Delta] | | [Delta] |
|
||||
* 0<---|sooner |<---|sooner |<---|sooner |<---ahb_latest
|
||||
* +----------+ +----------+ +----------+
|
||||
*
|
||||
* ahb_furtherest = sum(Delta[1..n])
|
||||
*/
|
||||
ahb_add_timeout(ecb,time)
|
||||
struct ecb *ecb;
|
||||
int time;
|
||||
|
||||
ahb_timeout(struct ecb *ecb)
|
||||
{
|
||||
int timeprev;
|
||||
struct ecb *prev;
|
||||
int s = splbio();
|
||||
|
||||
if(prev = ahb_latest) /* yes, an assign */
|
||||
{
|
||||
timeprev = ahb_furtherest;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeprev = 0;
|
||||
}
|
||||
while(prev && (timeprev > time))
|
||||
{
|
||||
timeprev -= prev->delta;
|
||||
prev = prev->sooner;
|
||||
}
|
||||
if(prev)
|
||||
{
|
||||
ecb->delta = time - timeprev;
|
||||
if( ecb->later = prev->later) /* yes an assign */
|
||||
{
|
||||
ecb->later->sooner = ecb;
|
||||
ecb->later->delta -= ecb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_furtherest = time;
|
||||
ahb_latest = ecb;
|
||||
}
|
||||
ecb->sooner = prev;
|
||||
prev->later = ecb;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ecb->later = ahb_soonest) /* yes, an assign*/
|
||||
{
|
||||
ecb->later->sooner = ecb;
|
||||
ecb->later->delta -= time;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_furtherest = time;
|
||||
ahb_latest = ecb;
|
||||
}
|
||||
ecb->delta = time;
|
||||
ecb->sooner = (struct ecb *)0;
|
||||
ahb_soonest = ecb;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
ahb_remove_timeout(ecb)
|
||||
struct ecb *ecb;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
if(ecb->sooner)
|
||||
{
|
||||
ecb->sooner->later = ecb->later;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_soonest = ecb->later;
|
||||
}
|
||||
if(ecb->later)
|
||||
{
|
||||
ecb->later->sooner = ecb->sooner;
|
||||
ecb->later->delta += ecb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
ahb_latest = ecb->sooner;
|
||||
ahb_furtherest -= ecb->delta;
|
||||
}
|
||||
ecb->sooner = ecb->later = (struct ecb *)0;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
extern int hz;
|
||||
#define ONETICK 500 /* milliseconds */
|
||||
#define SLEEPTIME ((hz * ONETICK) / 1000)
|
||||
ahb_timeout(arg)
|
||||
int arg;
|
||||
{
|
||||
struct ecb *ecb;
|
||||
int unit;
|
||||
int s = splbio();
|
||||
|
||||
while( ecb = ahb_soonest )
|
||||
unit = ecb->xs->adapter;
|
||||
printf("ahb%d:%d device timed out\n",unit
|
||||
,ecb->xs->targ);
|
||||
#ifdef AHBDEBUG
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
ahb_print_active_ecb(unit);
|
||||
#endif /*AHBDEBUG*/
|
||||
|
||||
/***************************************\
|
||||
* If it's immediate, don't try abort it *
|
||||
\***************************************/
|
||||
if(ecb->flags & ECB_IMMED)
|
||||
{
|
||||
if(ecb->delta <= ONETICK)
|
||||
/***********************************************\
|
||||
* It has timed out, we need to do some work *
|
||||
\***********************************************/
|
||||
{
|
||||
unit = ecb->xs->adapter;
|
||||
printf("ahb%d:%d device timed out\n",unit
|
||||
,ecb->xs->targ);
|
||||
if(ahb_debug & AHB_SHOWECBS)
|
||||
ahb_print_active_ecb();
|
||||
|
||||
/***************************************\
|
||||
* Unlink it from the queue *
|
||||
\***************************************/
|
||||
ahb_remove_timeout(ecb);
|
||||
|
||||
/***************************************\
|
||||
* If it's immediate, don't try abort it *
|
||||
\***************************************/
|
||||
if(ecb->flags & ECB_IMMED)
|
||||
{
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->flags |= ECB_IMMED_FAIL;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
continue;
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ecb->flags == ECB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("AGAIN");
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
|
||||
/* 2 secs for the abort */
|
||||
ahb_add_timeout(ecb,2000 + ONETICK);
|
||||
ecb->flags = ECB_ABORTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/***********************************************\
|
||||
* It has not timed out, adjust and leave *
|
||||
\***********************************************/
|
||||
{
|
||||
ecb->delta -= ONETICK;
|
||||
ahb_furtherest -= ONETICK;
|
||||
break;
|
||||
}
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->flags |= ECB_IMMED_FAIL;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
splx(s);
|
||||
return;
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ecb->flags == ECB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("AGAIN");
|
||||
ecb->xs->retries = 0; /* I MEAN IT ! */
|
||||
ecb->ecb_status.ha_status = HS_CMD_ABORTED_HOST;
|
||||
ahb_done(unit,ecb,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
ahb_send_mbox(unit,OP_ABORT_ECB,ecb->xs->targ,ecb);
|
||||
/* 2 secs for the abort */
|
||||
timeout(ahb_timeout,ecb,2 * hz);
|
||||
ecb->flags = ECB_ABORTED;
|
||||
}
|
||||
splx(s);
|
||||
timeout(ahb_timeout,arg,SLEEPTIME);
|
||||
}
|
||||
|
||||
#ifdef AHBDEBUG
|
||||
ahb_show_scsi_cmd(struct scsi_xfer *xs)
|
||||
{
|
||||
u_char *b = (u_char *)xs->cmd;
|
||||
|
|
@ -1419,24 +1309,26 @@ struct ecb *ecb;
|
|||
,ecb->opcode
|
||||
,ecb->cdblen
|
||||
,ecb->senselen);
|
||||
printf(" datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
|
||||
printf(" datlen:%d hstat:%x tstat:%x flags:%x\n"
|
||||
,ecb->datalen
|
||||
,ecb->ecb_status.ha_status
|
||||
,ecb->ecb_status.targ_status
|
||||
,ecb->delta
|
||||
,ecb->flags);
|
||||
ahb_show_scsi_cmd(ecb->xs);
|
||||
}
|
||||
|
||||
ahb_print_active_ecb()
|
||||
ahb_print_active_ecb(int unit)
|
||||
{
|
||||
struct ecb *ecb;
|
||||
ecb = ahb_soonest;
|
||||
struct ecb *ecb = ahb_data[unit].ecbs;
|
||||
int i = NUM_CONCURRENT;
|
||||
|
||||
while(ecb)
|
||||
while(i--)
|
||||
{
|
||||
ahb_print_ecb(ecb);
|
||||
ecb = ecb->later;
|
||||
if(ecb->flags != ECB_FREE)
|
||||
{
|
||||
ahb_print_ecb(ecb);
|
||||
}
|
||||
ecb++;
|
||||
}
|
||||
printf("Furtherest = %d\n",ahb_furtherest);
|
||||
}
|
||||
#endif /*AHBDEBUG */
|
||||
|
|
|
|||
|
|
@ -13,31 +13,32 @@
|
|||
* functioning of this software in any circumstances.
|
||||
*
|
||||
*
|
||||
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
|
||||
* -------------------- ----- ----------------------
|
||||
* CURRENT PATCH LEVEL: 1 00098
|
||||
* -------------------- ----- ----------------------
|
||||
*
|
||||
* 16 Feb 93 Julian Elischer ADDED for SCSI system
|
||||
*/
|
||||
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log: bt742a.c,v $
|
||||
* Revision 1.2 1993/07/29 11:55:35 nate
|
||||
* Syncing our sources back with Julian's, and removing PATCHKIT headers.
|
||||
*
|
||||
* Large Bustek changes, most everything else is minimal.
|
||||
*
|
||||
* Revision 1.1.1.1 1993/06/12 14:57:58 rgrimes
|
||||
* Initial import, 0.1 + pk 0.2.4-B1
|
||||
*
|
||||
* Revision 1.11 93/05/27 13:39:52 julian
|
||||
* $Log: bt742a.c,v $
|
||||
* Revision 1.12 93/08/07 13:20:44 julian
|
||||
* replace private timeout stuff with system timeout calls.
|
||||
*
|
||||
* Revision 1.11 93/05/27 13:39:52 root
|
||||
* Enable mail box round-robin scheme by new host adapter command appeared
|
||||
* at FirmWare V3.31 ( This release is shipped without testing at V3.31 )
|
||||
*
|
||||
* Revision 1.10 93/05/22 16:38:22 julian
|
||||
* Revision 1.10 93/05/22 16:38:22 root
|
||||
* under OSF, the dev_pic must be set up before it's used.
|
||||
* was only done ifndef OSF.
|
||||
*
|
||||
* Revision 1.9 93/05/07 11:37:24 julian
|
||||
* Revision 1.9 93/05/07 11:37:24 root
|
||||
* fix SLEEPTIME calculation.
|
||||
*
|
||||
* Revision 1.8 93/05/07 11:27:00 julian
|
||||
* Revision 1.8 93/05/07 11:27:00 root
|
||||
* Merge with 1.7.1
|
||||
*
|
||||
* Revision 1.7.1 1993/01/01 04:01:02 amurai
|
||||
|
|
@ -131,6 +132,7 @@ int Debugger();
|
|||
int Debugger();
|
||||
#endif MACH
|
||||
|
||||
extern int hz;
|
||||
extern int delaycount; /* from clock setup code */
|
||||
typedef unsigned long int physaddr;
|
||||
|
||||
|
|
@ -309,17 +311,12 @@ struct bt_ccb {
|
|||
/*------------------------------------longword boundary */
|
||||
struct bt_mbx_out *mbx; /* pointer to mail box */
|
||||
/*------------------------------------longword boundary */
|
||||
long int delta; /* difference from previous*/
|
||||
struct bt_ccb *later,*sooner;
|
||||
int flags;
|
||||
#define CCB_FREE 0
|
||||
#define CCB_ACTIVE 1
|
||||
#define CCB_ABORTED 2
|
||||
};
|
||||
|
||||
struct bt_ccb *bt_soonest = (struct bt_ccb *)0;
|
||||
struct bt_ccb *bt_latest = (struct bt_ccb *)0;
|
||||
long int bt_furtherest = 0; /* longest time in the timeout queue */
|
||||
/*
|
||||
* opcode fields
|
||||
*/
|
||||
|
|
@ -684,7 +681,7 @@ struct isa_dev *dev;
|
|||
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("bt%d: **probing for scsi devices**\n", unit);
|
||||
printf(" probing for scsi devices**\n");
|
||||
#endif __386BSD__
|
||||
|
||||
/***********************************************\
|
||||
|
|
@ -694,10 +691,6 @@ struct isa_dev *dev;
|
|||
#if defined(OSF)
|
||||
bt_attached[unit]=1;
|
||||
#endif /* defined(OSF) */
|
||||
if(!unit) /* only one for all boards */
|
||||
{
|
||||
bt_timeout(0);
|
||||
}
|
||||
#ifdef __386BSD__
|
||||
printf("bt%d",unit);
|
||||
#endif __386BSD__
|
||||
|
|
@ -822,7 +815,7 @@ AGAIN:
|
|||
wmbi->stat = BT_MBI_FREE;
|
||||
if(ccb)
|
||||
{
|
||||
bt_remove_timeout(ccb);
|
||||
untimeout(bt_timeout,ccb);
|
||||
bt_done(unit,ccb);
|
||||
}
|
||||
|
||||
|
|
@ -1537,7 +1530,7 @@ struct scsi_xfer *xs;
|
|||
#endif
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
{
|
||||
bt_add_timeout(ccb,xs->timeout);
|
||||
timeout(bt_timeout,ccb,(xs->timeout * hz) / 1000);
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
} else
|
||||
/***********************************************\
|
||||
|
|
@ -1610,174 +1603,57 @@ struct scsi_xfer *xs;
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* +----------+ +----------+ +----------+
|
||||
* bt_soonest--->| later |---->| later|---->| later|--->0
|
||||
* | [Delta] | | [Delta] | | [Delta] |
|
||||
* 0<-----|sooner |<----|sooner |<----|sooner |<----bt_latest
|
||||
* +----------+ +----------+ +----------+
|
||||
*
|
||||
* bt_furtherest = sum(Delta[1..n])
|
||||
*/
|
||||
bt_add_timeout(ccb,time)
|
||||
struct bt_ccb *ccb;
|
||||
int time;
|
||||
|
||||
bt_timeout(struct bt_ccb *ccb)
|
||||
{
|
||||
int timeprev;
|
||||
struct bt_ccb *prev;
|
||||
int s = splbio();
|
||||
|
||||
if(prev = bt_latest) /* yes, an assign */
|
||||
{
|
||||
timeprev = bt_furtherest;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeprev = 0;
|
||||
}
|
||||
while(prev && (timeprev > time))
|
||||
{
|
||||
timeprev -= prev->delta;
|
||||
prev = prev->sooner;
|
||||
}
|
||||
if(prev)
|
||||
{
|
||||
ccb->delta = time - timeprev;
|
||||
if( ccb->later = prev->later) /* yes an assign */
|
||||
{
|
||||
ccb->later->sooner = ccb;
|
||||
ccb->later->delta -= ccb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_furtherest = time;
|
||||
bt_latest = ccb;
|
||||
}
|
||||
ccb->sooner = prev;
|
||||
prev->later = ccb;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ccb->later = bt_soonest) /* yes, an assign*/
|
||||
{
|
||||
ccb->later->sooner = ccb;
|
||||
ccb->later->delta -= time;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_furtherest = time;
|
||||
bt_latest = ccb;
|
||||
}
|
||||
ccb->delta = time;
|
||||
ccb->sooner = (struct bt_ccb *)0;
|
||||
bt_soonest = ccb;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
bt_remove_timeout(ccb)
|
||||
struct bt_ccb *ccb;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
if(ccb->sooner)
|
||||
{
|
||||
ccb->sooner->later = ccb->later;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_soonest = ccb->later;
|
||||
}
|
||||
if(ccb->later)
|
||||
{
|
||||
ccb->later->sooner = ccb->sooner;
|
||||
ccb->later->delta += ccb->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt_latest = ccb->sooner;
|
||||
bt_furtherest -= ccb->delta;
|
||||
}
|
||||
ccb->sooner = ccb->later = (struct bt_ccb *)0;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
extern int hz;
|
||||
#define ONETICK 500 /* milliseconds */
|
||||
#define SLEEPTIME ((hz * ONETICK) / 1000)
|
||||
bt_timeout(arg)
|
||||
int arg;
|
||||
{
|
||||
struct bt_ccb *ccb;
|
||||
int unit;
|
||||
int s = splbio();
|
||||
|
||||
while( ccb = bt_soonest )
|
||||
{
|
||||
if(ccb->delta <= ONETICK)
|
||||
/***********************************************\
|
||||
* It has timed out, we need to do some work *
|
||||
\***********************************************/
|
||||
{
|
||||
unit = ccb->xfer->adapter;
|
||||
printf("bt%d:%d device timed out\n",unit
|
||||
,ccb->xfer->targ);
|
||||
if(bt_debug & BT_SHOWCCBS)
|
||||
tfs_print_active_ccbs();
|
||||
unit = ccb->xfer->adapter;
|
||||
printf("bt%d:%d device timed out\n",unit
|
||||
,ccb->xfer->targ);
|
||||
#ifdef UTEST
|
||||
if(bt_debug & BT_SHOWCCBS)
|
||||
bt_print_active_ccbs(unit);
|
||||
#endif
|
||||
|
||||
/***************************************\
|
||||
* Unlink it from the queue *
|
||||
\***************************************/
|
||||
bt_remove_timeout(ccb);
|
||||
/***************************************\
|
||||
* If The ccb's mbx is not free, then *
|
||||
* the board has gone Far East ? *
|
||||
\***************************************/
|
||||
if((struct bt_ccb *)PHYSTOKV(ccb->mbx->ccb_addr)==ccb &&
|
||||
ccb->mbx->cmd != BT_MBO_FREE )
|
||||
{
|
||||
printf("bt%d not taking commands!\n"
|
||||
,unit);
|
||||
Debugger();
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ccb->flags == CCB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("Abort Operation has timed out.\n");
|
||||
ccb->xfer->retries = 0; /* I MEAN IT ! */
|
||||
ccb->host_stat = BT_ABORTED;
|
||||
bt_done(unit,ccb);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("Try to abort\n");
|
||||
bt_send_mbo( unit, ~SCSI_NOMASK,
|
||||
BT_MBO_ABORT, ccb );
|
||||
/* 2 secs for the abort */
|
||||
bt_add_timeout(ccb,2000 + ONETICK);
|
||||
ccb->flags = CCB_ABORTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/***********************************************\
|
||||
* It has not timed out, adjust and leave *
|
||||
\***********************************************/
|
||||
{
|
||||
ccb->delta -= ONETICK;
|
||||
bt_furtherest -= ONETICK;
|
||||
break;
|
||||
}
|
||||
/***************************************\
|
||||
* If The ccb's mbx is not free, then *
|
||||
* the board has gone Far East ? *
|
||||
\***************************************/
|
||||
if((struct bt_ccb *)PHYSTOKV(ccb->mbx->ccb_addr)==ccb &&
|
||||
ccb->mbx->cmd != BT_MBO_FREE )
|
||||
{
|
||||
printf("bt%d not taking commands!\n"
|
||||
,unit);
|
||||
Debugger();
|
||||
}
|
||||
/***************************************\
|
||||
* If it has been through before, then *
|
||||
* a previous abort has failed, don't *
|
||||
* try abort again *
|
||||
\***************************************/
|
||||
if(ccb->flags == CCB_ABORTED) /* abort timed out */
|
||||
{
|
||||
printf("Abort Operation has timed out.\n");
|
||||
ccb->xfer->retries = 0; /* I MEAN IT ! */
|
||||
ccb->host_stat = BT_ABORTED;
|
||||
bt_done(unit,ccb);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("Try to abort\n");
|
||||
bt_send_mbo( unit, ~SCSI_NOMASK,
|
||||
BT_MBO_ABORT, ccb );
|
||||
/* 2 secs for the abort */
|
||||
timeout(bt_timeout,ccb,2 * hz);
|
||||
ccb->flags = CCB_ABORTED;
|
||||
}
|
||||
splx(s);
|
||||
timeout(bt_timeout,arg,SLEEPTIME);
|
||||
}
|
||||
|
||||
tfs_print_ccb(ccb)
|
||||
#ifdef UTEST
|
||||
bt_print_ccb(ccb)
|
||||
struct bt_ccb *ccb;
|
||||
{
|
||||
printf("ccb:%x op:%x cmdlen:%d senlen:%d\n"
|
||||
|
|
@ -1785,23 +1661,24 @@ struct bt_ccb *ccb;
|
|||
,ccb->opcode
|
||||
,ccb->scsi_cmd_length
|
||||
,ccb->req_sense_length);
|
||||
printf(" datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
|
||||
printf(" datlen:%d hstat:%x tstat:%x flags:%x\n"
|
||||
,ccb->data_length
|
||||
,ccb->host_stat
|
||||
,ccb->target_stat
|
||||
,ccb->delta
|
||||
,ccb->flags);
|
||||
}
|
||||
|
||||
tfs_print_active_ccbs()
|
||||
bt_print_active_ccbs(int unit)
|
||||
{
|
||||
struct bt_ccb *ccb;
|
||||
ccb = bt_soonest;
|
||||
ccb = &(bt_ccb[unit][0]);
|
||||
int i = BT_CCB_SIZE;
|
||||
|
||||
while(ccb)
|
||||
while(i--)
|
||||
{
|
||||
tfs_print_ccb(ccb);
|
||||
ccb = ccb->later;
|
||||
if(ccb->flags != CCB_FREE)
|
||||
bt_print_ccb(ccb);
|
||||
ccb++;
|
||||
}
|
||||
printf("Furtherest = %d\n",bt_furtherest);
|
||||
}
|
||||
#endif /*UTEST*/
|
||||
|
|
|
|||
|
|
@ -16,20 +16,13 @@
|
|||
* functioning of this software in any circumstances.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* HISTORY
|
||||
* $Log: ultra14f.c,v $
|
||||
* Revision 1.3 1993/07/29 11:55:37 nate
|
||||
* Syncing our sources back with Julian's, and removing PATCHKIT headers.
|
||||
*
|
||||
* Large Bustek changes, most everything else is minimal.
|
||||
*
|
||||
*
|
||||
* Revision 1.1 93/05/07 11:37:24 julian
|
||||
* fix SLEEPTIME calculation.
|
||||
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
|
||||
* -------------------- ----- ----------------------
|
||||
* CURRENT PATCH LEVEL: 1 00098
|
||||
* -------------------- ----- ----------------------
|
||||
*
|
||||
* 16 Feb 93 Julian Elischer ADDED for SCSI system
|
||||
* commenced: Sun Sep 27 18:14:01 PDT 1992
|
||||
* slight mod to make work with 34F as well: Wed Jun 2 18:05:48 WST 1993
|
||||
*/
|
||||
|
||||
|
|
@ -102,6 +95,7 @@ extern physaddr kvtophys();
|
|||
#define KVTOPHYS(x) vtophys(x)
|
||||
#endif __386BSD__
|
||||
|
||||
extern int hz;
|
||||
extern int delaycount; /* from clock setup code */
|
||||
#define NUM_CONCURRENT 16 /* number of concurrent ops per board */
|
||||
#define UHA_NSEG 33 /* number of dma segments supported */
|
||||
|
|
@ -251,8 +245,6 @@ struct mscp
|
|||
/*-----------------end of hardware supported fields----------------*/
|
||||
struct mscp *next; /* in free list */
|
||||
struct scsi_xfer *xs; /* the scsi_xfer for this cmd */
|
||||
long int delta; /* difference from previous*/
|
||||
struct mscp *later,*sooner;
|
||||
int flags;
|
||||
#define MSCP_FREE 0
|
||||
#define MSCP_ACTIVE 1
|
||||
|
|
@ -261,9 +253,6 @@ struct mscp
|
|||
struct scsi_sense_data mscp_sense;
|
||||
};
|
||||
|
||||
struct mscp *uha_soonest = (struct mscp *)0;
|
||||
struct mscp *uha_latest = (struct mscp *)0;
|
||||
long int uha_furtherest = 0; /* longest time in the timeout queue */
|
||||
/**/
|
||||
|
||||
struct uha_data
|
||||
|
|
@ -300,7 +289,9 @@ struct isa_driver uhadriver = { uhaprobe, uha_attach, "uha"};
|
|||
#endif __386BSD__
|
||||
|
||||
static uha_unit = 0;
|
||||
#ifdef UHADEBUG
|
||||
int uha_debug = 0;
|
||||
#endif /*UHADEBUG*/
|
||||
#define UHA_SHOWMSCPS 0x01
|
||||
#define UHA_SHOWINTS 0x02
|
||||
#define UHA_SHOWCMDS 0x04
|
||||
|
|
@ -458,7 +449,7 @@ struct isa_dev *dev;
|
|||
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("uha%d: **probing for scsi devices**\n", unit);
|
||||
printf(" probing for scsi devices**\n");
|
||||
#endif __386BSD__
|
||||
|
||||
/***********************************************\
|
||||
|
|
@ -469,11 +460,6 @@ struct isa_dev *dev;
|
|||
#if defined(OSF)
|
||||
uha_attached[unit]=1;
|
||||
#endif /* defined(OSF) */
|
||||
if(!unit) /* only one for all boards */
|
||||
{
|
||||
uha_timeout(0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __386BSD__
|
||||
printf("uha%d",unit);
|
||||
|
|
@ -503,8 +489,10 @@ uhaintr(unit)
|
|||
int port = uha_data[unit].baseport;
|
||||
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("uhaintr ");
|
||||
#endif /*UHADEBUG*/
|
||||
|
||||
#if defined(OSF)
|
||||
if (!uha_attached[unit])
|
||||
|
|
@ -522,21 +510,25 @@ uhaintr(unit)
|
|||
mboxval = inl(port + UHA_ICM0);
|
||||
outb(port + UHA_SINT,UHA_ICM_ACK);
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("status = 0x%x ",uhastat);
|
||||
#endif /*UHADEBUG*/
|
||||
/***********************************************\
|
||||
* Process the completed operation *
|
||||
\***********************************************/
|
||||
|
||||
mscp = (struct mscp *)(PHYSTOKV(mboxval));
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(uha_debug & UHA_SHOWCMDS )
|
||||
{
|
||||
uha_show_scsi_cmd(mscp->xs);
|
||||
}
|
||||
if((uha_debug & UHA_SHOWMSCPS) && mscp)
|
||||
printf("<int mscp(%x)>",mscp);
|
||||
uha_remove_timeout(mscp);
|
||||
#endif /*UHADEBUG*/
|
||||
untimeout(uha_timeout,mscp);
|
||||
|
||||
uha_done(unit,mscp);
|
||||
}
|
||||
|
|
@ -556,8 +548,10 @@ struct mscp *mscp;
|
|||
struct scsi_sense_data *s1,*s2;
|
||||
struct scsi_xfer *xs = mscp->xs;
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & (PRINTROUTINES | TRACEINTERRUPTS))
|
||||
printf("uha_done ");
|
||||
#endif /*UHADEBUG*/
|
||||
/***********************************************\
|
||||
* Otherwise, put the results of the operation *
|
||||
* into the xfer and call whoever started it *
|
||||
|
|
@ -578,33 +572,41 @@ struct mscp *mscp;
|
|||
switch(mscp->ha_status)
|
||||
{
|
||||
case UHA_SBUS_TIMEOUT: /* No response */
|
||||
#ifdef UHADEBUG
|
||||
if (uha_debug & UHA_SHOWMISC)
|
||||
{
|
||||
printf("timeout reported back\n");
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
xs->error = XS_TIMEOUT;
|
||||
break;
|
||||
case UHA_SBUS_OVER_UNDER:
|
||||
#ifdef UHADEBUG
|
||||
if (uha_debug & UHA_SHOWMISC)
|
||||
{
|
||||
printf("scsi bus xfer over/underrun\n");
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
break;
|
||||
case UHA_BAD_SG_LIST:
|
||||
#ifdef UHADEBUG
|
||||
if (uha_debug & UHA_SHOWMISC)
|
||||
{
|
||||
printf("bad sg list reported back\n");
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
break;
|
||||
default: /* Other scsi protocol messes */
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
#ifdef UHADEBUG
|
||||
if (uha_debug & UHA_SHOWMISC)
|
||||
{
|
||||
printf("unexpected ha_status: %x\n",
|
||||
mscp->ha_status);
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -619,11 +621,13 @@ struct mscp *mscp;
|
|||
\**************************************************************************/
|
||||
|
||||
{
|
||||
#ifdef UHADEBUG
|
||||
if (uha_debug & UHA_SHOWMISC)
|
||||
{
|
||||
printf("unexpected targ_status: %x\n",
|
||||
mscp->targ_status);
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
}
|
||||
}
|
||||
|
|
@ -643,8 +647,10 @@ struct mscp *mscp;
|
|||
{
|
||||
unsigned int opri;
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("mscp%d(0x%x)> ",unit,flags);
|
||||
#endif /*UHADEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
|
||||
|
|
@ -671,8 +677,10 @@ uha_get_mscp(unit,flags)
|
|||
unsigned opri;
|
||||
struct mscp *rc;
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("<mscp%d(0x%x) ",unit,flags);
|
||||
#endif /*UHADEBUG*/
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
/***********************************************\
|
||||
|
|
@ -845,8 +853,10 @@ struct scsi_xfer *xs;
|
|||
unsigned long int templen;
|
||||
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & PRINTROUTINES)
|
||||
printf("uha_scsi_cmd ");
|
||||
#endif /*UHADEBUG*/
|
||||
/***********************************************\
|
||||
* get a mscp (mbox-out) to use. If the transfer *
|
||||
* is from a buf (possibly from interrupt time) *
|
||||
|
|
@ -871,12 +881,14 @@ struct scsi_xfer *xs;
|
|||
}
|
||||
|
||||
cheat = mscp;
|
||||
#ifdef UHADEBUG
|
||||
if(uha_debug & UHA_SHOWMSCPS)
|
||||
printf("<start mscp(%x)>",mscp);
|
||||
if(scsi_debug & SHOWCOMMANDS)
|
||||
{
|
||||
uha_show_scsi_cmd(xs);
|
||||
}
|
||||
#endif /*UHADEBUG*/
|
||||
mscp->xs = xs;
|
||||
/***********************************************\
|
||||
* Put all the arguments for the xfer in the mscp *
|
||||
|
|
@ -952,10 +964,12 @@ cheat = mscp;
|
|||
sg->addr.addr[2] = ((scratch >> 16) & 0xff);
|
||||
sg->addr.addr[3] = ((scratch >> 24) & 0xff);
|
||||
xs->datalen += *(unsigned long *)sg->len.len = iovp->iov_len;
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x@0x%x)"
|
||||
,iovp->iov_len
|
||||
,iovp->iov_base);
|
||||
#endif /*UHADEBUG*/
|
||||
sg++;
|
||||
iovp++;
|
||||
seg++;
|
||||
|
|
@ -968,8 +982,10 @@ cheat = mscp;
|
|||
* Set up the scatter gather block *
|
||||
\***********************************************/
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("%d @0x%x:- ",xs->datalen,xs->data);
|
||||
#endif /*UHADEBUG*/
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
|
|
@ -985,8 +1001,10 @@ cheat = mscp;
|
|||
sg->addr.addr[2] = ((thisphys >> 16) & 0xff);
|
||||
sg->addr.addr[3] = ((thisphys >> 24) & 0xff);
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("0x%x",thisphys);
|
||||
#endif /*UHADEBUG*/
|
||||
|
||||
/* do it at least once */
|
||||
nextphys = thisphys;
|
||||
|
|
@ -1015,8 +1033,10 @@ cheat = mscp;
|
|||
/********************************************\
|
||||
* next page isn't contiguous, finish the seg *
|
||||
\********************************************/
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("(0x%x)",bytes_this_seg);
|
||||
#endif /*UHADEBUG*/
|
||||
sg->len.len[0] = (bytes_this_seg & 0xff);
|
||||
sg->len.len[1] = ((bytes_this_seg >> 8) & 0xff);
|
||||
sg->len.len[2] = ((bytes_this_seg >> 16) & 0xff);
|
||||
|
|
@ -1032,8 +1052,10 @@ cheat = mscp;
|
|||
mscp->datalen.len[3] = ((templen >> 24) & 0xff);
|
||||
mscp->sg_num = seg;
|
||||
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & SHOWSCATGATH)
|
||||
printf("\n");
|
||||
#endif /*UHADEBUG*/
|
||||
if (datalen)
|
||||
{ /* there's still data, must have run out of segs! */
|
||||
printf("uha_scsi_cmd%d: more than %d DMA segs\n",
|
||||
|
|
@ -1071,18 +1093,22 @@ cheat = mscp;
|
|||
{
|
||||
s = splbio();
|
||||
uha_send_mbox(unit,mscp);
|
||||
uha_add_timeout(mscp,xs->timeout);
|
||||
timeout(uha_timeout,mscp,(xs->timeout * hz) / 1000);
|
||||
splx(s);
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_sent ");
|
||||
#endif /*UHADEBUG*/
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
/***********************************************\
|
||||
* If we can't use interrupts, poll on completion*
|
||||
\***********************************************/
|
||||
uha_send_mbox(unit,mscp);
|
||||
#ifdef UHADEBUG
|
||||
if(scsi_debug & TRACEINTERRUPTS)
|
||||
printf("cmd_wait ");
|
||||
#endif /*UHADEBUG*/
|
||||
do
|
||||
{
|
||||
if(uha_poll(unit,xs->timeout))
|
||||
|
|
@ -1094,12 +1120,9 @@ cheat = mscp;
|
|||
uha_free_mscp(unit,mscp,flags);
|
||||
}
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
splx(s);
|
||||
return(HAD_ERROR);
|
||||
}
|
||||
} while (!(xs->flags & ITSDONE));/* something (?) else finished */
|
||||
splx(s);
|
||||
scsi_debug = 0;uha_debug = 0;
|
||||
if(xs->error)
|
||||
{
|
||||
return(HAD_ERROR);
|
||||
|
|
@ -1107,154 +1130,34 @@ scsi_debug = 0;uha_debug = 0;
|
|||
return(COMPLETE);
|
||||
}
|
||||
|
||||
/*
|
||||
* +----------+ +----------+ +----------+
|
||||
* uha_soonest--->| later |--->| later|--->| later|--->0
|
||||
* | [Delta] | | [Delta] | | [Delta] |
|
||||
* 0<---|sooner |<---|sooner |<---|sooner |<---uha_latest
|
||||
* +----------+ +----------+ +----------+
|
||||
*
|
||||
* uha_furtherest = sum(Delta[1..n])
|
||||
*/
|
||||
uha_add_timeout(mscp,time)
|
||||
struct mscp *mscp;
|
||||
int time;
|
||||
|
||||
uha_timeout(struct mscp *mscp)
|
||||
{
|
||||
int timeprev;
|
||||
struct mscp *prev;
|
||||
int s = splbio();
|
||||
|
||||
if(prev = uha_latest) /* yes, an assign */
|
||||
{
|
||||
timeprev = uha_furtherest;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeprev = 0;
|
||||
}
|
||||
while(prev && (timeprev > time))
|
||||
{
|
||||
timeprev -= prev->delta;
|
||||
prev = prev->sooner;
|
||||
}
|
||||
if(prev)
|
||||
{
|
||||
mscp->delta = time - timeprev;
|
||||
if( mscp->later = prev->later) /* yes an assign */
|
||||
{
|
||||
mscp->later->sooner = mscp;
|
||||
mscp->later->delta -= mscp->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
uha_furtherest = time;
|
||||
uha_latest = mscp;
|
||||
}
|
||||
mscp->sooner = prev;
|
||||
prev->later = mscp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mscp->later = uha_soonest) /* yes, an assign*/
|
||||
{
|
||||
mscp->later->sooner = mscp;
|
||||
mscp->later->delta -= time;
|
||||
}
|
||||
else
|
||||
{
|
||||
uha_furtherest = time;
|
||||
uha_latest = mscp;
|
||||
}
|
||||
mscp->delta = time;
|
||||
mscp->sooner = (struct mscp *)0;
|
||||
uha_soonest = mscp;
|
||||
}
|
||||
splx(s);
|
||||
}
|
||||
|
||||
uha_remove_timeout(mscp)
|
||||
struct mscp *mscp;
|
||||
{
|
||||
int s = splbio();
|
||||
|
||||
if(mscp->sooner)
|
||||
{
|
||||
mscp->sooner->later = mscp->later;
|
||||
}
|
||||
else
|
||||
{
|
||||
uha_soonest = mscp->later;
|
||||
}
|
||||
if(mscp->later)
|
||||
{
|
||||
mscp->later->sooner = mscp->sooner;
|
||||
mscp->later->delta += mscp->delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
uha_latest = mscp->sooner;
|
||||
uha_furtherest -= mscp->delta;
|
||||
}
|
||||
mscp->sooner = mscp->later = (struct mscp *)0;
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
||||
extern int hz;
|
||||
#define ONETICK 500 /* milliseconds */
|
||||
#define SLEEPTIME ((hz * ONETICK) / 1000)
|
||||
uha_timeout(arg)
|
||||
int arg;
|
||||
{
|
||||
struct mscp *mscp;
|
||||
int unit;
|
||||
int s = splbio();
|
||||
unsigned int stat;
|
||||
int port = uha_data[unit].baseport;
|
||||
|
||||
while( mscp = uha_soonest )
|
||||
unit = mscp->xs->adapter;
|
||||
printf("uha%d:%d device timed out\n",unit
|
||||
,mscp->xs->targ);
|
||||
#ifdef UHADEBUG
|
||||
if(uha_debug & UHA_SHOWMSCPS)
|
||||
uha_print_active_mscp(unit);
|
||||
#endif /*UHADEBUG*/
|
||||
|
||||
if((uha_abort(unit,mscp) !=1) || (mscp->flags = MSCP_ABORTED))
|
||||
{
|
||||
if(mscp->delta <= ONETICK)
|
||||
/***********************************************\
|
||||
* It has timed out, we need to do some work *
|
||||
\***********************************************/
|
||||
{
|
||||
unit = mscp->xs->adapter;
|
||||
printf("uha%d:%d device timed out\n",unit
|
||||
,mscp->xs->targ);
|
||||
if(uha_debug & UHA_SHOWMSCPS)
|
||||
uha_print_active_mscp();
|
||||
|
||||
/***************************************\
|
||||
* Unlink it from the queue *
|
||||
\***************************************/
|
||||
uha_remove_timeout(mscp);
|
||||
|
||||
if((uha_abort(unit,mscp) !=1) || (mscp->flags = MSCP_ABORTED))
|
||||
{
|
||||
printf("AGAIN");
|
||||
mscp->xs->retries = 0; /* I MEAN IT ! */
|
||||
uha_done(unit,mscp,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
uha_add_timeout(mscp,2000 + ONETICK);
|
||||
mscp->flags = MSCP_ABORTED;
|
||||
}
|
||||
}
|
||||
else
|
||||
/***********************************************\
|
||||
* It has not timed out, adjust and leave *
|
||||
\***********************************************/
|
||||
{
|
||||
mscp->delta -= ONETICK;
|
||||
uha_furtherest -= ONETICK;
|
||||
break;
|
||||
}
|
||||
printf("AGAIN");
|
||||
mscp->xs->retries = 0; /* I MEAN IT ! */
|
||||
uha_done(unit,mscp,FAIL);
|
||||
}
|
||||
else /* abort the operation that has timed out */
|
||||
{
|
||||
printf("\n");
|
||||
timeout(uha_timeout,mscp,2 * hz);
|
||||
mscp->flags = MSCP_ABORTED;
|
||||
}
|
||||
splx(s);
|
||||
timeout(uha_timeout,arg,SLEEPTIME);
|
||||
}
|
||||
|
||||
uha_show_scsi_cmd(struct scsi_xfer *xs)
|
||||
|
|
@ -1291,26 +1194,25 @@ struct mscp *mscp;
|
|||
,mscp->opcode
|
||||
,mscp->cdblen
|
||||
,mscp->senselen);
|
||||
printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x delta:%d flags:%x\n"
|
||||
printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
|
||||
,mscp->sgth
|
||||
,mscp->sg_num
|
||||
,mscp->datalen
|
||||
,mscp->ha_status
|
||||
,mscp->targ_status
|
||||
,mscp->delta
|
||||
,mscp->flags);
|
||||
uha_show_scsi_cmd(mscp->xs);
|
||||
}
|
||||
|
||||
uha_print_active_mscp()
|
||||
uha_print_active_mscp(int unit)
|
||||
{
|
||||
struct mscp *mscp;
|
||||
mscp = uha_soonest;
|
||||
struct mscp *mscp = uha_data[unit].mscps;
|
||||
int i = NUHA;
|
||||
|
||||
while(mscp)
|
||||
while(i--)
|
||||
{
|
||||
uha_print_mscp(mscp);
|
||||
mscp = mscp->later;
|
||||
if(mscp->flags != MSCP_FREE)
|
||||
uha_print_mscp(mscp);
|
||||
mscp++;
|
||||
}
|
||||
printf("Furtherest = %d\n",uha_furtherest);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue