bt.c, aic7xxx.c:

Cleanse the SCSI subsystem of its internally defined types
	u_int32, u_int16, u_int8, int32, int16, int8.
	Use the system defined *_t types instead.

aic7xxx.c:
	Fix the reset code.
	Instead of queing up all of the SCBs that timeout during timeout
	processing, we take the first and have it champion the effort.
	Any other scbs that timeout during timeout handling are given
	another lifetime to complete in the hopes that once timeout
	handing is finished, they will complete normally.  If one of
	these SCBs times out a second time, we panic and Justin tries
	again.

	The other major change is to queue flag aborted SCBs during timeout
	handling, and "ahc_done" them all at once as soon as we have the
	controller back into a sane state.  Calling ahc_done any earlier
	will cause the SCSI subsystem to toss the command right back at
	us and the attempt to queue the command will conflict with what
	the timeout routine is trying to accomplish.

	The aic7xxx driver will now respond to bus resets initiated by
	other devices.
This commit is contained in:
Justin T. Gibbs 1996-03-10 07:11:45 +00:00
parent 58a8ca6a4d
commit 9dfa2063d5
3 changed files with 247 additions and 239 deletions

View File

@ -24,7 +24,7 @@
*
* commenced: Sun Sep 27 18:14:01 PDT 1992
*
* $Id: aic7xxx.c,v 1.54 1996/01/23 21:47:50 se Exp $
* $Id: aic7xxx.c,v 1.55 1996/01/29 03:17:37 gibbs Exp $
*/
/*
* TODO:
@ -70,14 +70,9 @@ static int ahc_debug = AHC_SHOWABORTS|AHC_SHOWMISC;
#define HSCSIID 0x07 /* our SCSI ID */
#define HWSCSIID 0x0f /* our SCSI ID if Wide Bus */
typedef enum {
list_head,
list_second,
}insert_t;
static u_int32 ahc_adapter_info __P((int unit));
static void ahcminphys __P((struct buf *bp));
static int32 ahc_scsi_cmd __P((struct scsi_xfer *xs));
static u_int32_t ahc_adapter_info __P((int unit));
static void ahcminphys __P((struct buf *bp));
static int32_t ahc_scsi_cmd __P((struct scsi_xfer *xs));
static struct scsi_adapter ahc_switch =
{
@ -129,13 +124,12 @@ static struct scsi_device ahc_dev =
static u_char ahc_abort_wscb __P((struct ahc_data *ahc, struct scb *scbp,
u_char prev, u_long iobase,
u_char timedout_scb, u_int32 xs_error));
static void ahc_add_waiting_scb __P((u_long iobase, struct scb *scb,
insert_t where));
u_char timedout_scb, u_int32_t xs_error));
static void ahc_add_waiting_scb __P((u_long iobase, struct scb *scb));
static void ahc_done __P((struct ahc_data *ahc, struct scb *scbp));
static void ahc_free_scb __P((struct ahc_data *ahc, struct scb *scb,
int flags));
static inline void ahc_getscb __P((struct ahc_data *ahc, struct scb *scb,
static inline void ahc_fetch_scb __P((struct ahc_data *ahc, struct scb *scb,
int iosize));
static struct scb *
ahc_get_scb __P((struct ahc_data *ahc, int flags));
@ -147,16 +141,16 @@ static void ahc_print_active_scb __P((struct ahc_data *ahc));
static void ahc_print_scb __P((struct scb *scb));
#endif
static int ahc_reset_channel __P((struct ahc_data *ahc, char channel,
u_char timedout_scb, u_int32 xs_error));
u_char timedout_scb, u_int32_t xs_error,
u_char initiate_reset));
static int ahc_reset_device __P((struct ahc_data *ahc, int target,
char channel, u_char timedout_scb,
u_int32 xs_error));
u_int32_t xs_error));
static void ahc_reset_current_bus __P((u_long iobase));
static void ahc_scb_timeout __P((struct ahc_data *ahc, struct scb *scb));
static void ahc_run_done_queue __P((struct ahc_data *ahc));
static void ahc_scsirate __P((struct ahc_data* ahc, u_char *scsirate,
int period, int offset, int target));
static inline void ahc_send_scb __P((struct ahc_data *ahc, struct scb *scb,
int iosize));
static inline void ahc_send_scb __P((struct ahc_data *ahc, struct scb *scb));
static timeout_t
ahc_timeout;
static void ahc_busy_target __P((int target, char channel,
@ -439,10 +433,9 @@ ahc_attach(ahc)
/* Send an SCB down to the card via PIO maintaining the SCB pointer */
static inline void
ahc_send_scb(ahc, scb, iosize)
ahc_send_scb(ahc, scb)
struct ahc_data *ahc;
struct scb *scb;
int iosize; /* In bytes */
{
u_long iobase = ahc->baseport;
u_char cur_scb;
@ -452,15 +445,16 @@ ahc_send_scb(ahc, scb, iosize)
outb(SCBCNT + iobase, SCBAUTO);
if( ahc->type == AHC_284 )
/* Can only do 8bit PIO */
outsb(SCBARRAY+iobase, scb, iosize);
outsb(SCBARRAY+iobase, scb, SCB_PIO_TRANSFER_SIZE);
else
outsl(SCBARRAY+iobase, scb, (iosize + 3) / 4);
outsl(SCBARRAY+iobase, scb,
(SCB_PIO_TRANSFER_SIZE + 3) / 4);
outb(SCBCNT + iobase, 0);
outb(SCBPTR + iobase, cur_scb);
}
static inline void
ahc_getscb(ahc, scb, iosize)
ahc_fetch_scb(ahc, scb, iosize)
struct ahc_data *ahc;
struct scb *scb;
int iosize;
@ -476,43 +470,28 @@ ahc_getscb(ahc, scb, iosize)
}
/*
* Add this SCB to the "waiting for selection" list.
* Add this SCB to the head of the "waiting for selection" list.
*/
static
void ahc_add_waiting_scb (iobase, scb, where)
void ahc_add_waiting_scb (iobase, scb)
u_long iobase;
struct scb *scb;
insert_t where;
{
u_char head, tail;
u_char next;
u_char curscb;
curscb = inb(SCBPTR + iobase);
head = inb(WAITING_SCBH + iobase);
if(head == SCB_LIST_NULL) {
/* List was empty */
head = scb->position;
tail = SCB_LIST_NULL;
}
else if (where == list_head) {
outb(SCBPTR+iobase, scb->position);
outb(SCB_NEXT_WAITING+iobase, head);
head = scb->position;
}
else /*where == list_second*/ {
u_char third_scb;
outb(SCBPTR+iobase, head);
third_scb = inb(SCB_NEXT_WAITING+iobase);
outb(SCB_NEXT_WAITING+iobase,scb->position);
outb(SCBPTR+iobase, scb->position);
outb(SCB_NEXT_WAITING+iobase,third_scb);
}
outb(WAITING_SCBH + iobase, head);
next = inb(WAITING_SCBH + iobase);
outb(SCBPTR+iobase, scb->position);
outb(SCB_NEXT_WAITING+iobase, next);
outb(WAITING_SCBH + iobase, scb->position);
outb(SCBPTR + iobase, curscb);
}
/*
* Catch an interrupt from the adaptor
* Catch an interrupt from the adapter
*/
void
ahc_intr(arg)
@ -837,7 +816,7 @@ ahc_intr(arg)
xs = scb->xs;
ahc_getscb(ahc, scb, SCB_PIO_TRANSFER_SIZE);
ahc_fetch_scb(ahc, scb, SCB_PIO_TRANSFER_SIZE);
#ifdef AHC_DEBUG
if((ahc_debug & AHC_SHOWSCBS)
@ -893,8 +872,7 @@ ahc_intr(arg)
scb->data = sg->addr;
scb->datalen = sg->len;
ahc_send_scb(ahc, scb,
SCB_PIO_TRANSFER_SIZE);
ahc_send_scb(ahc, scb);
outb(SCB_NEXT_WAITING+iobase,
SCB_LIST_NULL);
/*
@ -908,8 +886,7 @@ ahc_intr(arg)
/*
* Make us the next command to run
*/
ahc_add_waiting_scb(iobase, scb,
list_head);
ahc_add_waiting_scb(iobase, scb);
outb(RETURN_1 + iobase, SEND_SENSE);
break;
}
@ -1061,13 +1038,11 @@ ahc_intr(arg)
found = ahc_reset_device(ahc, target,
channel, SCB_LIST_NULL,
XS_NOERROR);
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS) {
sc_print_addr(scb->xs->sc_link);
printf("Bus Device Reset delivered. "
"%d SCBs aborted\n", found);
}
#endif
sc_print_addr(scb->xs->sc_link);
printf("Bus Device Reset delivered. "
"%d SCBs aborted\n", found);
ahc->in_timeout = FALSE;
ahc_run_done_queue(ahc);
}
else
panic("ahc_intr: Immediate complete for "
@ -1183,10 +1158,26 @@ clear:
}
xs = scb->xs;
if (status & SCSIRSTI) {
u_char channel;
PAUSE_SEQUENCER(ahc);
channel = inb(SBLKCTL + iobase);
if( !(inb(SCSISEQ + iobase ) & SCSIRSTO)
&& (ahc->flags & AHC_TWIN) )
{
/* Its on the other bus */
channel ^= SELBUSB;
}
ahc_reset_channel(ahc,
channel & SELBUSB ? 'B' : 'A',
SCB_LIST_NULL,
XS_BUSY,
/* Initiate Reset */FALSE);
ahc_run_done_queue(ahc);
}
if (status & SELTO) {
u_char waiting;
u_char flags;
outb(SCSISEQ + iobase, ENRSELI);
xs->error = XS_TIMEOUT;
/*
* Clear any pending messages for the timed out
@ -1377,7 +1368,7 @@ ahc_init(ahc)
outb(SCSIID + iobase, ahc->our_id_b);
scsi_conf = inb(SCSICONF + 1 + iobase) & (ENSPCHK|STIMESEL);
outb(SXFRCTL1 + iobase, scsi_conf|ENSTIMER|ACTNEGEN|STPWEN);
outb(SIMODE1 + iobase, ENSELTIMO);
outb(SIMODE1 + iobase, ENSELTIMO|ENSCSIRST);
if(ahc->type & AHC_ULTRA)
outb(SXFRCTL0 + iobase, DFON|SPIOEN|ULTRAEN);
else
@ -1394,7 +1385,7 @@ ahc_init(ahc)
outb(SCSIID + iobase, ahc->our_id);
scsi_conf = inb(SCSICONF + iobase) & (ENSPCHK|STIMESEL);
outb(SXFRCTL1 + iobase, scsi_conf|ENSTIMER|ACTNEGEN|STPWEN);
outb(SIMODE1 + iobase, ENSELTIMO);
outb(SIMODE1 + iobase, ENSELTIMO|ENSCSIRST);
if(ahc->type & AHC_ULTRA)
outb(SXFRCTL0 + iobase, DFON|SPIOEN|ULTRAEN);
else
@ -1555,7 +1546,7 @@ ahcminphys(bp)
* the data address, target, and lun all of which
* are stored in the scsi_xfer struct
*/
static int32
static int32_t
ahc_scsi_cmd(xs)
struct scsi_xfer *xs;
{
@ -1689,7 +1680,7 @@ ahc_scsi_cmd(xs)
ahc->unit, AHC_NSEG);
xs->error = XS_DRIVER_STUFFUP;
ahc_free_scb(ahc, scb, flags);
return (HAD_ERROR);
return (COMPLETE);
}
}
else {
@ -1709,7 +1700,7 @@ ahc_scsi_cmd(xs)
if (!(flags & SCSI_NOMASK)) {
s = splbio();
PAUSE_SEQUENCER(ahc);
ahc_send_scb(ahc, scb, SCB_PIO_TRANSFER_SIZE);
ahc_send_scb(ahc, scb);
outb(QINFIFO + ahc->baseport, scb->position);
UNPAUSE_SEQUENCER(ahc);
timeout(ahc_timeout, (caddr_t)scb, (xs->timeout * hz) / 1000);
@ -1722,7 +1713,7 @@ ahc_scsi_cmd(xs)
*/
s = splbio();
PAUSE_SEQUENCER(ahc);
ahc_send_scb(ahc, scb, SCB_PIO_TRANSFER_SIZE);
ahc_send_scb(ahc, scb);
outb(QINFIFO + ahc->baseport, scb->position);
UNPAUSE_SEQUENCER(ahc);
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_wait\n"));
@ -1730,15 +1721,10 @@ ahc_scsi_cmd(xs)
if (ahc_poll(ahc, xs->timeout)) {
if (!(xs->flags & SCSI_SILENT))
printf("cmd fail\n");
ahc_scb_timeout(ahc, scb);
splx(s);
return (HAD_ERROR);
ahc_timeout(scb);
break;
}
} while (!(xs->flags & ITSDONE)); /* a non command complete intr */
if (xs->error) {
splx(s);
return (HAD_ERROR);
}
splx(s);
return (COMPLETE);
}
@ -1748,7 +1734,7 @@ ahc_scsi_cmd(xs)
* Return some information to the caller about
* the adapter and it's capabilities.
*/
static u_int32
static u_int32_t
ahc_adapter_info(unit)
int unit;
{
@ -1808,8 +1794,6 @@ ahc_get_scb(ahc, flags)
scbp = (struct scb *) malloc(sizeof(struct scb),
M_TEMP, M_NOWAIT);
if (scbp) {
u_long iobase = ahc->baseport;
u_char curscb;
bzero(scbp, sizeof(struct scb));
scbp->position = ahc->numscbs;
ahc->numscbs++;
@ -1898,66 +1882,149 @@ ahc_poll(ahc, wait)
}
static void
ahc_scb_timeout(ahc, scb)
struct ahc_data *ahc;
struct scb *scb;
ahc_timeout(arg)
void *arg;
{
u_long iobase = ahc->baseport;
int found = 0;
char channel = scb->target_channel_lun & SELBUSB ? 'B': 'A';
struct scb *scb = (struct scb *)arg;
struct ahc_data *ahc;
int s, h, found;
u_char bus_state;
u_long iobase;
/*
s = splbio();
h = splhigh();
if (!(scb->flags & SCB_ACTIVE)) {
/* Previous timeout took care of me already */
splx(h);
splx(s);
return;
}
ahc = (struct ahc_data *)scb->xs->sc_link->adapter_softc;
if (ahc->in_timeout) {
/*
* Some other SCB has started a recovery operation
* and is still working on cleaning things up.
*/
if (scb->flags & SCB_TIMEDOUT) {
/*
* This SCB has been here before and is not the
* recovery SCB. Cut our losses and panic. Its
* better to do this than trash a filesystem.
*/
panic("ahc%d: Timed-out command times out "
"again\n", ahc->unit);
}
else if (!(scb->flags & SCB_ABORTED))
{
/*
* This is not the SCB that started this timeout
* processing. Give this scb another lifetime so
* that it can continue once we deal with the
* timeout.
*/
scb->flags |= SCB_TIMEDOUT;
timeout(ahc_timeout, (caddr_t)scb,
(scb->xs->timeout * hz) / 1000);
splx(h);
splx(s);
return;
}
}
ahc->in_timeout = TRUE;
splx(h);
/*
* Ensure that the card doesn't do anything
* behind our back.
*/
PAUSE_SEQUENCER(ahc);
sc_print_addr(scb->xs->sc_link);
printf("timed out ");
/*
* First, determine if we want to do a bus
* reset or simply a bus device reset.
* If this is the first time that a transaction
* has timed out, just schedule a bus device
* reset. Otherwise, we reset the bus and
* abort all pending I/Os on that bus.
* Take a snapshot of the bus state and print out
* some information so we can track down driver bugs.
*/
iobase = ahc->baseport;
bus_state = inb(iobase + LASTPHASE);
switch(bus_state & PHASE_MASK)
{
case P_DATAOUT:
printf("in dataout phase");
break;
case P_DATAIN:
printf("in datain phase");
break;
case P_COMMAND:
printf("in command phase");
break;
case P_MESGOUT:
printf("in message out phase");
break;
case P_STATUS:
printf("in status phase");
break;
case P_MESGIN:
printf("in message in phase");
break;
default:
printf("while idle, LASTPHASE == 0x%x",
bus_state);
/*
* We aren't in a valid phase, so assume we're
* idle.
*/
bus_state = 0;
break;
}
printf(", SCSISIGI == 0x%x\n", inb(iobase + SCSISIGI));
/* Decide our course of action */
if(scb->flags & SCB_ABORTED)
{
/*
* Been down this road before.
* Do a full bus reset.
*/
char channel = (scb->target_channel_lun & SELBUSB)
? 'B': 'A';
found = ahc_reset_channel(ahc, channel, scb->position,
XS_TIMEOUT);
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS)
printf("ahc%d: Issued Channel %c Bus Reset #1. "
"%d SCBs aborted\n", ahc->unit, channel, found);
#endif
XS_TIMEOUT, /*Initiate Reset*/TRUE);
printf("ahc%d: Issued Channel %c Bus Reset #1. "
"%d SCBs aborted\n", ahc->unit, channel, found);
ahc->in_timeout = FALSE;
}
else {
/*
* Send a Bus Device Reset Message:
* The target we select to send the message to may
* be entirely different than the target pointed to
* by the scb that timed out. If the command is
* in the QINFIFO or the waiting for selection list,
* its not tying up the bus and isn't responsible
* for the delay so we pick off the active command
* which should be the SCB selected by SCBPTR. If
* its disconnected or active, we device reset the
* target scbp points to. Although it may be that
* this target is not responsible for the delay, it
* may also be that we're timing out on a command that
* just takes too much time, so we try the bus device
* reset there first.
* The target that is holding up the bus may not
* be the same as the one that triggered this timeout
* (different commands have different timeout lengths).
* It is also impossible to get a message to a target
* if we are in a "frozen" data transfer phase. Our
* strategy here is to queue a bus device reset message
* to the timed out target if it is disconnected.
* Otherwise, if we have an active target we stuff the
* message buffer with a bus device reset message and
* assert ATN in the hopes that the target will let go
* of the bus and finally disconnect. If this fails,
* we'll get another timeout 2 seconds later which will
* cause a bus reset.
*/
u_char active_scb, control;
struct scb *active_scbp;
active_scb = inb(SCBPTR + iobase);
active_scbp = ahc->scbarray[active_scb];
control = inb(SCBARRAY + iobase);
control = inb(SCB_CONTROL + iobase);
/* Test to see if scbp is disconnected */
/* Test to see if scb is disconnected */
outb(SCBPTR + iobase, scb->position);
if(inb(SCB_CONTROL + iobase) & DISCONNECTED) {
scb->flags |= SCB_DEVICE_RESET|SCB_ABORTED;
@ -1965,123 +2032,44 @@ ahc_scb_timeout(ahc, scb)
scb->SG_list_pointer = 0;
scb->data = 0;
scb->datalen = 0;
outb(SCBCNT + iobase, 0x80);
outsb(SCBARRAY+iobase,scb,SCB_PIO_TRANSFER_SIZE);
outb(SCBCNT + iobase, 0);
ahc_add_waiting_scb(iobase, scb, list_second);
ahc_send_scb(ahc, scb);
ahc_add_waiting_scb(iobase, scb);
timeout(ahc_timeout, (caddr_t)scb, (2 * hz));
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS) {
sc_print_addr(scb->xs->sc_link);
printf("BUS DEVICE RESET message queued.\n");
}
#endif
sc_print_addr(scb->xs->sc_link);
printf("BUS DEVICE RESET message queued.\n");
outb(SCBPTR + iobase, active_scb);
UNPAUSE_SEQUENCER(ahc);
}
/* Is the active SCB really active? */
else if(active_scbp->flags & SCB_ACTIVE) {
/* XXX && (control & NEEDDMA) == NEEDDMA) { */
u_char msg_len = inb(MSG_LEN + iobase);
if(msg_len) {
/*
* If we're in a message phase, tacking on
* another message may confuse the target totally.
* The bus is probably wedged, so reset the
* channel.
*/
channel = (active_scbp->target_channel_lun & SELBUSB)
? 'B': 'A';
ahc_reset_channel(ahc, channel, scb->position,
XS_TIMEOUT);
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS)
printf("ahc%d: Issued Channel %c Bus Reset #2. "
"%d SCBs aborted\n", ahc->unit, channel,
found);
#endif
}
else {
/*
* Load the message buffer and assert attention.
*/
active_scbp->flags |= SCB_DEVICE_RESET|SCB_ABORTED;
if(active_scbp != scb)
untimeout(ahc_timeout, (caddr_t)active_scbp);
timeout(ahc_timeout, (caddr_t)active_scbp, (2 * hz));
else if((active_scbp->flags & SCB_ACTIVE) && bus_state) {
outb(MSG_LEN + iobase, 1);
outb(MSG0 + iobase, MSG_BUS_DEVICE_RESET);
if(active_scbp->target_channel_lun
!= scb->target_channel_lun) {
outb(SCSISIGO + iobase, bus_state|ATNO);
sc_print_addr(active_scbp->xs->sc_link);
printf("asserted ATN - device reset in message buffer\n");
active_scbp->flags |= SCB_DEVICE_RESET|SCB_ABORTED;
if(active_scbp != scb) {
untimeout(ahc_timeout, (caddr_t)active_scbp);
/* Give scb a new lease on life */
timeout(ahc_timeout, (caddr_t)scb,
(scb->xs->timeout * hz) / 1000);
}
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS) {
sc_print_addr(active_scbp->xs->sc_link);
printf("BUS DEVICE RESET message queued.\n");
}
#endif
timeout(ahc_timeout, (caddr_t)active_scbp, (2 * hz));
outb(SCBPTR + iobase, active_scb);
UNPAUSE_SEQUENCER(ahc);
}
}
else {
/*
* No active command to single out, so reset
* the bus for the timed out target.
*/
ahc_reset_channel(ahc, channel, scb->position,
XS_TIMEOUT);
#ifdef AHC_DEBUG
if(ahc_debug & AHC_SHOWABORTS)
printf("ahc%d: Issued Channel %c Bus Reset #3. "
"%d SCBs aborted\n", ahc->unit, channel,
found);
#endif
/* No active target? Try reseting the bus */
char channel = (scb->target_channel_lun & SELBUSB)
? 'B': 'A';
found = ahc_reset_channel(ahc, channel, scb->position,
XS_TIMEOUT, /*Initiate Reset*/TRUE);
printf("ahc%d: Issued Channel %c Bus Reset #2. "
"%d SCBs aborted\n", ahc->unit, channel,
found);
ahc->in_timeout = FALSE;
}
}
}
static void
ahc_timeout(void *arg1)
{
struct scb *scb = (struct scb *)arg1;
struct ahc_data *ahc;
int s;
s = splhigh();
if (!(scb->flags & SCB_ACTIVE)) {
/* Previous timeout took care of me already */
splx(s);
return;
}
ahc = (struct ahc_data *)scb->xs->sc_link->adapter_softc;
printf("ahc%d: target %d, lun %d (%s%d) timed out\n", ahc->unit
,scb->xs->sc_link->target
,scb->xs->sc_link->lun
,scb->xs->sc_link->device->name
,scb->xs->sc_link->dev_unit);
#ifdef SCSIDEBUG
show_scsi_cmd(scb->xs);
#endif
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOWSCBS)
ahc_print_active_scb(ahc);
#endif /*AHC_DEBUG */
/*
* If it's immediate, don't try to abort it
*/
if (scb->flags & SCB_IMMED) {
scb->xs->retries = 0; /* I MEAN IT ! */
ahc_done(ahc, scb);
}
else {
/* abort the operation that has timed out */
ahc_scb_timeout(ahc, scb);
}
splx(s);
}
@ -2096,7 +2084,7 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
int target;
char channel;
u_char timedout_scb;
u_int32 xs_error;
u_int32_t xs_error;
{
u_long iobase = ahc->baseport;
struct scb *scbp;
@ -2121,11 +2109,10 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
/*
* We found an scb that needs to be aborted.
*/
scbp->flags |= SCB_ABORTED;
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
scbp->xs->error |= xs_error;
if(scbp->position != timedout_scb)
untimeout(ahc_timeout, (caddr_t)scbp);
ahc_done (ahc, scbp);
outb(SCBPTR + iobase, scbp->position);
outb(SCBARRAY + iobase, 0);
i--;
@ -2178,11 +2165,10 @@ ahc_reset_device(ahc, target, channel, timedout_scb, xs_error)
ahc_unbusy_target(target, channel, iobase);
outb(SCBPTR + iobase, scbp->position);
outb(SCBARRAY + iobase, 0);
scbp->flags |= SCB_ABORTED;
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
scbp->xs->error |= xs_error;
if(scbp->position != timedout_scb)
untimeout(ahc_timeout, (caddr_t)scbp);
ahc_done (ahc, scbp);
found++;
}
}
@ -2201,7 +2187,7 @@ ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
u_char prev;
u_long iobase;
u_char timedout_scb;
u_int32 xs_error;
u_int32_t xs_error;
{
u_char curscbp, next;
int target = ((scbp->target_channel_lun >> 4) & 0x0f);
@ -2215,7 +2201,7 @@ ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
next = inb(SCB_NEXT_WAITING + iobase);
/* Clear the necessary fields */
outb(SCBARRAY + iobase, 0);
outb(SCB_CONTROL + iobase, 0);
outb(SCB_NEXT_WAITING + iobase, SCB_LIST_NULL);
ahc_unbusy_target(target, channel, iobase);
@ -2231,21 +2217,16 @@ ahc_abort_wscb (ahc, scbp, prev, iobase, timedout_scb, xs_error)
outb(SCBPTR + iobase, prev);
outb(SCB_NEXT_WAITING + iobase, next);
}
/* Update the tale pointer */
if(inb(WAITING_SCBT + iobase) == scbp->position)
outb(WAITING_SCBT + iobase, prev);
/*
* Point us back at the original scb position
* and inform the SCSI system that the command
* has been aborted.
*/
outb(SCBPTR + iobase, curscbp);
scbp->flags |= SCB_ABORTED;
scbp->flags = SCB_ABORTED|SCB_QUEUED_FOR_DONE;
scbp->xs->error |= xs_error;
if(scbp->position != timedout_scb)
untimeout(ahc_timeout, (caddr_t)scbp);
ahc_done (ahc, scbp);
return next;
}
@ -2301,11 +2282,12 @@ ahc_reset_current_bus(iobase)
}
static int
ahc_reset_channel(ahc, channel, timedout_scb, xs_error)
ahc_reset_channel(ahc, channel, timedout_scb, xs_error, initiate_reset)
struct ahc_data *ahc;
char channel;
u_char timedout_scb;
u_int32 xs_error;
u_int32_t xs_error;
u_char initiate_reset;
{
u_long iobase = ahc->baseport;
u_char sblkctl;
@ -2355,9 +2337,9 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error)
}
/*
* Reset the bus and unpause/restart the controller
* Reset the bus if we are initiating this reset and
* restart/unpause the sequencer
*/
/* Case 1: Command for another bus is active */
sblkctl = inb(SBLKCTL + iobase);
cur_channel = (sblkctl & SELBUSB) ? 'B' : 'A';
@ -2368,18 +2350,41 @@ ahc_reset_channel(ahc, channel, timedout_scb, xs_error)
* without upsetting the current bus
*/
outb(SBLKCTL + iobase, sblkctl ^ SELBUSB);
ahc_reset_current_bus(iobase);
if( initiate_reset )
{
ahc_reset_current_bus(iobase);
}
outb(CLRSINT1 + iobase, CLRSCSIRSTI);
outb(SBLKCTL + iobase, sblkctl);
UNPAUSE_SEQUENCER(ahc);
}
/* Case 2: A command from this bus is active or we're idle */
else {
ahc_reset_current_bus(iobase);
if( initiate_reset )
{
ahc_reset_current_bus(iobase);
}
outb(CLRSINT1 + iobase, CLRSCSIRSTI);
RESTART_SEQUENCER(ahc);
}
ahc_run_done_queue(ahc);
return found;
}
void
ahc_run_done_queue(ahc)
struct ahc_data *ahc;
{
int i;
struct scb *scbp;
for(i = 0; i < ahc->numscbs; i++) {
scbp = ahc->scbarray[i];
if(scbp->flags & SCB_QUEUED_FOR_DONE)
ahc_done(ahc, scbp);
}
}
static int
ahc_match_scb (scb, target, channel)
struct scb *scb;

View File

@ -20,7 +20,7 @@
* 4. Modifications may be freely made to this file if the above conditions
* are met.
*
* $Id: aic7xxx.h,v 1.20 1996/01/29 03:17:39 gibbs Exp $
* $Id: aic7xxx.h,v 1.21 1996/01/30 22:56:41 mpp Exp $
*/
#ifndef _AIC7XXX_H_
@ -124,6 +124,8 @@ struct scb {
#define SCB_DEVICE_RESET 0x04
#define SCB_IMMED 0x08
#define SCB_SENSE 0x10
#define SCB_TIMEDOUT 0x20
#define SCB_QUEUED_FOR_DONE 0x40
int position; /* Position in scbarray */
struct ahc_dma_seg ahc_dma[AHC_NSEG] __attribute__ ((packed));
struct scsi_sense sense_cmd; /* SCSI command block */
@ -155,6 +157,7 @@ struct ahc_data {
u_char maxscbs;
u_char unpause;
u_char pause;
u_char in_timeout;
};
/* Different debugging levels used when AHC_DEBUG is defined */

View File

@ -12,7 +12,7 @@
* on the understanding that TFS is not responsible for the correct
* functioning of this software in any circumstances.
*
* $Id: bt.c,v 1.6 1996/02/16 17:23:56 gibbs Exp $
* $Id: bt.c,v 1.7 1996/02/18 07:45:36 gibbs Exp $
*/
/*
@ -183,7 +183,7 @@ struct bt_ext_info {
u_char bios_addr; /* Bios Address-Not used */
u_short max_seg; /* Max segment List */
u_char num_mbx; /* Number of mailbox */
int32 mbx_base; /* mailbox base address */
int32_t mbx_base; /* mailbox base address */
struct {
u_char resv1:1; /* ??? */
u_char force:1; /* ON: force sync */
@ -219,7 +219,7 @@ struct bt_sync_value {
static int bt_debug = 0;
SYSCTL_INT(_debug, OID_AUTO, bt_debug, CTLFLAG_RW, &bt_debug, 0, "");
static u_int32 bt_adapter_info __P((int unit));
static u_int32_t bt_adapter_info __P((int unit));
static struct bt_ccb *
bt_ccb_phys_kv __P((struct bt_data *bt, physaddr ccb_phys));
#ifdef notyet
@ -242,7 +242,7 @@ static int bt_poll __P((struct bt_data *bt, struct scsi_xfer *xs,
static void bt_print_active_ccbs __P((int unit));
static void bt_print_ccb __P((struct bt_ccb *ccb));
#endif
static int32 bt_scsi_cmd __P((struct scsi_xfer *xs));
static int32_t bt_scsi_cmd __P((struct scsi_xfer *xs));
static BT_MBO * bt_send_mbo __P((struct bt_data *bt, int flags, int cmd,
struct bt_ccb *ccb));
static timeout_t
@ -526,7 +526,7 @@ bt_attach(bt)
* Return some information to the caller about the adapter and its
* capabilities.
*/
static u_int32
static u_int32_t
bt_adapter_info(unit)
int unit;
{
@ -1237,7 +1237,7 @@ btminphys(bp)
* start a scsi operation given the command and the data address. Also needs
* the unit, target and lu.
*/
static int32
static int32_t
bt_scsi_cmd(xs)
struct scsi_xfer *xs;
{