* Ported for use with the UltraStor 14f by Gary Close (gclose@wvnvms.wvnet.edu)
* Thanks to Julian Elischer for advice and help with this port.
* Written by Julian Elischer (julian@tfs.com)
* for TRW Financial Systems for use under the MACH(2.5) operating system.
* TRW Financial Systems, in accordance with their agreement with Carnegie
* Mellon University, makes this software available to CMU to distribute
* or use in any manner that they see fit as long as this message is kept with
* the software. For this reason TFS also grants any other persons or
* organisations permission to use or modify this software.
* 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.
* 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
* $Id: ultra14f.c,v 1.10 1993/10/14 00:07:04 rgrimes Exp $
#ifdef MACH /* EITHER CMU OR OSF */
#include <i386at/scsiconf.h>
#ifdef OSF /* OSF ONLY */
#include <i386/handler.h>
#include <i386/dispatcher.h>
#include <i386/AT386/atbus.h>
#include <i386at/atbus.h>
#endif MACH /* end of MACH specific */
#ifdef __386BSD__ /* 386BSD specific */
#define isa_dev isa_device
#define dev_addr id_iobase
#include <i386/include/pio.h>
#include <i386/isa/isa_device.h>
#include <scsi/scsi_all.h>
#include <scsi/scsiconf.h>
#define Debugger() panic("should call debugger here")
typedef struct {unsigned char addr
[4]; } physaddr
;
typedef struct {unsigned char len
[4]; } physlen
;
extern physaddr
kvtophys();
#define PHYSTOKV(x) phystokv(x)
#define KVTOPHYS(x) kvtophys(x)
#define KVTOPHYS(x) vtophys(x)
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 */
#define FUDGE(X) (X>>1) /* our loops are slower than spinwait() */
/************************** board definitions *******************************/
#define UHA_LMASK (0x000) /* local doorbell mask reg */
#define UHA_LINT (0x001) /* local doorbell int/stat reg */
#define UHA_SMASK (0x002) /* system doorbell mask reg */
#define UHA_SINT (0x003) /* system doorbell int/stat reg */
#define UHA_ID0 (0x004) /* product id reg 0 */
#define UHA_ID1 (0x005) /* product id reg 1 */
#define UHA_CONF1 (0x006) /* config reg 1 */
#define UHA_CONF2 (0x007) /* config reg 2 */
#define UHA_OGM0 (0x008) /* outgoing mail ptr 0 least sig */
#define UHA_OGM1 (0x009) /* outgoing mail ptr 1 least mid */
#define UHA_OGM2 (0x00a) /* outgoing mail ptr 2 most mid */
#define UHA_OGM3 (0x00b) /* outgoing mail ptr 3 most sig */
#define UHA_ICM0 (0x00c) /* incoming mail ptr 0 */
#define UHA_ICM1 (0x00d) /* incoming mail ptr 1 */
#define UHA_ICM2 (0x00e) /* incoming mail ptr 2 */
#define UHA_ICM3 (0x00f) /* incoming mail ptr 3 */
* UHA_LMASK bits (read only)
#define UHA_LDIE 0x80 /* local doorbell int enabled */
#define UHA_SRSTE 0x40 /* soft reset enabled */
#define UHA_ABORTEN 0x10 /* abort MSCP enabled */
#define UHA_OGMINTEN 0x01 /* outgoing mail interrupt enabled */
#define UHA_LDIP 0x80 /* local doorbell int pending */
#define UHA_ADRST 0x40 /* adapter soft reset */
#define UHA_SBRST 0x20 /* scsi bus reset */
#define UHA_ASRST 0x60 /* adapter and scsi reset */
#define UHA_ABORT 0x10 /* abort MSCP */
#define UHA_OGMINT 0x01 /* tell adapter to get mail */
#define UHA_SINTEN 0x80 /* system doorbell interupt Enabled */
#define UHA_ABORT_COMPLETE_EN 0x10 /* abort MSCP command complete int Enabled */
#define UHA_ICM_ENABLED 0x01 /* ICM interrupt enabled */
#define UHA_ENSINT 0x80 /* enable system doorbell interrupt */
#define UHA_EN_ABORT_COMPLETE 0x10 /* enable abort MSCP complete int */
#define UHA_ENICM 0x01 /* enable ICM interrupt */
#define UHA_SINTP 0x80 /* system doorbell int pending */
#define UHA_ABORT_SUCC 0x10 /* abort MSCP successful */
#define UHA_ABORT_FAIL 0x18 /* abort MSCP failed */
#define UHA_ABORT_ACK 0x18 /* acknowledge status and clear */
#define UHA_ICM_ACK 0x01 /* acknowledge ICM and clear */
* UHA_CONF1 bits (read only)
#define UHA_DMA_CH5 0x00 /* DMA channel 5 */
#define UHA_DMA_CH6 0x40 /* 6 */
#define UHA_DMA_CH7 0x80 /* 7 */
#define UHA_IRQ15 0x00 /* IRQ 15 */
#define UHA_IRQ14 0x10 /* 14 */
#define UHA_IRQ11 0x20 /* 11 */
#define UHA_IRQ10 0x30 /* 10 */
/***********************************
\***********************************/
#define UHA_NO_ERR 0x00 /* No error supposedly */
#define UHA_SBUS_ABORT_ERR 0x84 /* scsi bus abort error */
#define UHA_SBUS_TIMEOUT 0x91 /* scsi bus selection timeout */
#define UHA_SBUS_OVER_UNDER 0x92 /* scsi bus over/underrun */
#define UHA_BAD_SCSI_CMD 0x96 /* illegal scsi command */
#define UHA_AUTO_SENSE_ERR 0x9b /* auto request sense err */
#define UHA_SBUS_RES_ERR 0xa3 /* scsi bus reset error */
#define UHA_BAD_SG_LIST 0xff /* invalid scatter gath list */
#define U14_HAC 0x01 /*host adapter command*/
#define U14_TSP 0x02 /*target scsi pass through command*/
#define U14_SDR 0x04 /*scsi device reset*/
unsigned char xdir
:2; /*xfer direction*/
#define U14_SDET 0x00 /*determined by scsi command*/
#define U14_SDIN 0x01 /*scsi data in*/
#define U14_SDOUT 0x02 /*scsi data out*/
#define U14_NODATA 0x03 /*no data xfer*/
unsigned char dcn
:1; /*disable disconnect for this command*/
unsigned char ca
:1; /*Cache control*/
unsigned char sgth
:1; /*scatter gather flag*/
unsigned char chan
:2; /*scsi channel (always 0 for 14f)*/
unsigned char sg_num
; /*number of scat gath segs */
/*in s-g list if sg flag is*/
/*set. starts at 1, 8bytes per*/
unsigned char targ_status
;
physaddr sense
; /* if 0 no auto sense */
/*-----------------end of hardware supported fields----------------*/
struct mscp
*next
; /* in free list */
struct scsi_xfer
*xs
; /* the scsi_xfer for this cmd */
struct uha_dma_seg uha_dma
[UHA_NSEG
];
struct scsi_sense_data mscp_sense
;
struct mscp mscps
[NUM_CONCURRENT
];
int our_id
; /* our scsi id */
long int uha_adapter_info();
unsigned long int scratch
;
struct isa_driver uhadriver
= { uhaprobe
, 0, uha_attach
, "uha", 0, 0, 0};
int (*uhaintrs
[])() = {uhaintr
, 0};
struct isa_driver uhadriver
= { uhaprobe
, uha_attach
, "uha"};
#define UHA_SHOWMSCPS 0x01
#define UHA_SHOWINTS 0x02
#define UHA_SHOWCMDS 0x04
#define UHA_SHOWMISC 0x08
struct scsi_switch uha_switch
=
/***********************************************************************\
* Function to send a command out through a mailbox *
\***********************************************************************/
int port
= uha_data
[unit
].baseport
;
int spincount
= FUDGE(delaycount
) * 1000; /* 1s should be enough */
while( ((inb(port
+ UHA_LINT
) & (UHA_LDIP
))
printf("uha%d: uha_send_mbox, board not responding\n",unit
);
outl(port
+ UHA_OGM0
,KVTOPHYS(mscp
));
outb(port
+ UHA_LINT
, (UHA_OGMINT
));
/***********************************************************************\
* Function to send abort to 14f *
\***********************************************************************/
int port
= uha_data
[unit
].baseport
;
int spincount
= FUDGE(delaycount
) * 1;
int abortcount
= FUDGE(delaycount
) * 2000;
while(((inb(port
+ UHA_LINT
) & (UHA_LDIP
))
printf("uha%d: uha_abort, board not responding\n",unit
);
outl(port
+ UHA_OGM0
,KVTOPHYS(mscp
));
outb(port
+ UHA_LINT
,UHA_ABORT
);
while((abortcount
--) && (!(inb(port
+ UHA_SINT
) & UHA_ABORT_FAIL
)));
printf("uha%d: uha_abort, board not responding\n",unit
);
if((inb(port
+ UHA_SINT
) & 0x10) != 0)
outb(port
+ UHA_SINT
,UHA_ABORT_ACK
);
outb(port
+ UHA_SINT
,UHA_ABORT_ACK
);
/***********************************************************************\
* Function to poll for command completion when in poll mode *
\***********************************************************************/
uha_poll(int unit
,int wait
) /* in msec */
int port
= uha_data
[unit
].baseport
;
int spincount
= FUDGE(delaycount
) * wait
; /* in msec */
int stport
= port
+ UHA_SINT
;
while( (spincount
--) && (!(inb(stport
) & UHA_SINTP
)));
printf("uha%d: uha_poll, board not responding\n",unit
);
if ((int)cheat
!= PHYSTOKV(inl(port
+ UHA_ICM0
)))
printf("uha%d: discarding %x\n",unit
,inl(port
+ UHA_ICM0
));
outb(port
+ UHA_SINT
, UHA_ICM_ACK
);
}/* don't know this will work */
/*******************************************************\
* Check if the device can be found at the port given *
* and if so, set it up ready for further work *
* as an argument, takes the isa_dev structure from *
\*******************************************************/
uha_data
[unit
].baseport
= dev
->dev_addr
;
printf("uha%d: unit number too high\n",unit
);
/*try and initialize unit at this location*/
/* if its there put in it's interrupt and DRQ vectors */
dev
->id_irq
= (1 << uha_data
[unit
].vect
);
dev
->id_drq
= uha_data
[unit
].dma
;
/***********************************************\
* Attach all the sub-devices we can find *
\***********************************************/
int unit
= dev
->dev_unit
;
/***********************************************\
* ask the adapter what subunits are present *
\***********************************************/
scsi_attachdevs( unit
, uha_data
[unit
].our_id
, &uha_switch
);
#endif /* defined(OSF) */
/***********************************************\
* Return some information to the caller about *
* the adapter and it's capabilities *
\***********************************************/
long int uha_adapter_info(unit
)
return(2); /* 2 outstanding requests at a time per device */
/***********************************************\
* Catch an interrupt from the adaptor *
\***********************************************/
unsigned long int mboxval
;
int port
= uha_data
[unit
].baseport
;
if(scsi_debug
& PRINTROUTINES
)
#endif /* defined(OSF) */
while(inb(port
+ UHA_SINT
) & UHA_SINTP
)
/***********************************************\
* First get all the information and then *
* acknowlege the interrupt *
\***********************************************/
uhastat
= inb(port
+ UHA_SINT
);
mboxval
= inl(port
+ UHA_ICM0
);
outb(port
+ UHA_SINT
,UHA_ICM_ACK
);
if(scsi_debug
& TRACEINTERRUPTS
)
printf("status = 0x%x ",uhastat
);
/***********************************************\
* Process the completed operation *
\***********************************************/
mscp
= (struct mscp
*)(PHYSTOKV(mboxval
));
if(uha_debug
& UHA_SHOWCMDS
)
uha_show_scsi_cmd(mscp
->xs
);
if((uha_debug
& UHA_SHOWMSCPS
) && mscp
)
printf("<int mscp(%x)>",mscp
);
untimeout(uha_timeout
,mscp
);
/***********************************************\
* We have a mscp which has been processed by the *
* adaptor, now we look to see how the operation *
\***********************************************/
struct scsi_sense_data
*s1
,*s2
;
struct scsi_xfer
*xs
= mscp
->xs
;
if(scsi_debug
& (PRINTROUTINES
| TRACEINTERRUPTS
))
/***********************************************\
* Otherwise, put the results of the operation *
* into the xfer and call whoever started it *
\***********************************************/
if ( (mscp
->ha_status
== UHA_NO_ERR
) || (xs
->flags
& SCSI_ERR_OK
))
{ /* All went correctly OR errors expected */
s1
= &(mscp
->mscp_sense
);
if(mscp
->ha_status
!= UHA_NO_ERR
)
case UHA_SBUS_TIMEOUT
: /* No response */
if (uha_debug
& UHA_SHOWMISC
)
printf("timeout reported back\n");
case UHA_SBUS_OVER_UNDER
:
if (uha_debug
& UHA_SHOWMISC
)
printf("scsi bus xfer over/underrun\n");
xs
->error
= XS_DRIVER_STUFFUP
;
if (uha_debug
& UHA_SHOWMISC
)
printf("bad sg list reported back\n");
xs
->error
= XS_DRIVER_STUFFUP
;
default: /* Other scsi protocol messes */
xs
->error
= XS_DRIVER_STUFFUP
;
if (uha_debug
& UHA_SHOWMISC
)
printf("unexpected ha_status: %x\n",
if (mscp
->targ_status
!= 0)
/**************************************************************************\
* I have no information for any possible value of target status field *
* other than 0 means no error!! So I guess any error is unexpected in that *
\**************************************************************************/
if (uha_debug
& UHA_SHOWMISC
)
printf("unexpected targ_status: %x\n",
xs
->error
= XS_DRIVER_STUFFUP
;
done
: xs
->flags
|= ITSDONE
;
uha_free_mscp(unit
,mscp
, xs
->flags
);
(*(xs
->when_done
))(xs
->done_arg
,xs
->done_arg2
);
/***********************************************\
* A mscp (and hence a mbx-out is put onto the *
\***********************************************/
uha_free_mscp(unit
,mscp
, flags
)
if(scsi_debug
& PRINTROUTINES
)
printf("mscp%d(0x%x)> ",unit
,flags
);
if (!(flags
& SCSI_NOMASK
))
mscp
->next
= uha_data
[unit
].free_mscp
;
uha_data
[unit
].free_mscp
= mscp
;
/***********************************************\
* If there were none, wake abybody waiting for *
* one to come free, starting with queued entries*
\***********************************************/
wakeup(&uha_data
[unit
].free_mscp
);
if (!(flags
& SCSI_NOMASK
))
/***********************************************\
* Get a free mscp (and hence mbox-out entry) *
\***********************************************/
if(scsi_debug
& PRINTROUTINES
)
printf("<mscp%d(0x%x) ",unit
,flags
);
if (!(flags
& SCSI_NOMASK
))
/***********************************************\
* If we can and have to, sleep waiting for one *
\***********************************************/
while ((!(rc
= uha_data
[unit
].free_mscp
)) && (!(flags
& SCSI_NOSLEEP
)))
sleep(&uha_data
[unit
].free_mscp
, PRIBIO
);
uha_data
[unit
].free_mscp
= rc
->next
;
if (!(flags
& SCSI_NOMASK
))
/***********************************************\
* Start the board, ready for normal operation *
\***********************************************/
volatile unsigned char model
;
volatile unsigned char submodel
;
unsigned char config_reg1
;
unsigned char config_reg2
;
int port
= uha_data
[unit
].baseport
;
int resetcount
= FUDGE(delaycount
) * 4000;
model
= inb(port
+ UHA_ID0
);
submodel
= inb(port
+ UHA_ID1
);
if ((model
!= 0x56) & (submodel
!= 0x40)) {
printf("uha%d: uha_init, board not responding\n",unit
);
printf("uha%d: reading board settings, ",unit
);
config_reg1
= inb(port
+ UHA_CONF1
);
config_reg2
= inb(port
+ UHA_CONF2
);
dma_ch
= (config_reg1
& 0xc0);
irq_ch
= (config_reg1
& 0x30);
uha_id
= (config_reg2
& 0x07);
printf("illegal dma jumper setting\n");
uha_data
[unit
].vect
= 10;
uha_data
[unit
].vect
= 11;
uha_data
[unit
].vect
= 14;
uha_data
[unit
].vect
= 15;
printf("illegal int jumper setting\n");
/* who are we on the scsi bus */
printf("id=%x\n",uha_id
);
uha_data
[unit
].our_id
= uha_id
;
/***********************************************\
* link up all our MSCPs into a free list *
\***********************************************/
for (i
=0; i
< NUM_CONCURRENT
; i
++)
uha_data
[unit
].mscps
[i
].next
= uha_data
[unit
].free_mscp
;
uha_data
[unit
].free_mscp
= &uha_data
[unit
].mscps
[i
];
uha_data
[unit
].free_mscp
->flags
= MSCP_FREE
;
/***********************************************\
* Note that we are going and return (to probe) *
\***********************************************/
outb(port
+ UHA_LINT
, UHA_ASRST
);
while( (resetcount
--) && (!(inb(port
+ UHA_LINT
))));
printf("uha%d: board timed out during reset\n",unit
);
outb(port
+ UHA_SMASK
, 0x81); /* make sure interrupts are enabled */
uha_data
[unit
].flags
|= UHA_INIT
;
#define min(x,y) (x < y ? x : y)
bp
->b_flags
|= B_NPAGES
; /* can support scat/gather */
#endif /* defined(OSF) */
if(bp
->b_bcount
> ((UHA_NSEG
-1) * PAGESIZ
))
bp
->b_bcount
= ((UHA_NSEG
-1) * PAGESIZ
);
/***********************************************\
* start a scsi operation given the command and *
* the data address. Also needs the unit, target *
\***********************************************/
struct scsi_sense_data
*s1
,*s2
;
int seg
; /* scatter gather seg being worked on */
unsigned long int thisphys
,nextphys
;
int bytes_this_seg
,bytes_this_page
,datalen
,flags
;
int port
= uha_data
[unit
].baseport
;
unsigned long int templen
;
if(scsi_debug
& PRINTROUTINES
)
/***********************************************\
* get a mscp (mbox-out) to use. If the transfer *
* is from a buf (possibly from interrupt time) *
* then we can't allow it to sleep *
\***********************************************/
if(xs
->bp
) flags
|= (SCSI_NOSLEEP
); /* just to be sure */
printf("uha%d: Already done?",unit
);
printf("uha%d: Not in use?",unit
);
if (!(mscp
= uha_get_mscp(unit
,flags
)))
xs
->error
= XS_DRIVER_STUFFUP
;
if(uha_debug
& UHA_SHOWMSCPS
)
printf("<start mscp(%x)>",mscp
);
if(scsi_debug
& SHOWCOMMANDS
)
/***********************************************\
* Put all the arguments for the xfer in the mscp *
\***********************************************/
if (flags
& SCSI_DATA_IN
)
if (flags
& SCSI_DATA_OUT
)
xs
->error
= XS_DRIVER_STUFFUP
;
uha_free_mscp(unit
,mscp
,flags
);
mscp
->link
.addr
[0] = 0x00;
mscp
->link
.addr
[1] = 0x00;
mscp
->link
.addr
[2] = 0x00;
mscp
->link
.addr
[3] = 0x00;
mscp
->cdblen
= xs
->cmdlen
;
scratch
= KVTOPHYS(&(mscp
->mscp_sense
));
mscp
->sense
.addr
[0] = (scratch
& 0xff);
mscp
->sense
.addr
[1] = ((scratch
>> 8) & 0xff);
mscp
->sense
.addr
[2] = ((scratch
>> 16) & 0xff);
mscp
->sense
.addr
[3] = ((scratch
>> 24) & 0xff);
mscp
->senselen
= sizeof(mscp
->mscp_sense
);
mscp
->targ_status
= 0x00;
{ /* should use S/G only if not zero length */
scratch
= KVTOPHYS(mscp
->uha_dma
);
mscp
->data
.addr
[0] = (scratch
& 0xff);
mscp
->data
.addr
[1] = ((scratch
>> 8) & 0xff);
mscp
->data
.addr
[2] = ((scratch
>> 16) & 0xff);
mscp
->data
.addr
[3] = ((scratch
>> 24) & 0xff);
if(flags
& SCSI_DATA_UIO
)
iovp
= ((struct uio
*)xs
->data
)->uio_iov
;
datalen
= ((struct uio
*)xs
->data
)->uio_iovcnt
;
while ((datalen
) && (seg
< UHA_NSEG
))
scratch
= (unsigned long)iovp
->iov_base
;
sg
->addr
.addr
[0] = (scratch
& 0xff);
sg
->addr
.addr
[1] = ((scratch
>> 8) & 0xff);
sg
->addr
.addr
[2] = ((scratch
>> 16) & 0xff);
sg
->addr
.addr
[3] = ((scratch
>> 24) & 0xff);
xs
->datalen
+= *(unsigned long *)sg
->len
.len
= iovp
->iov_len
;
if(scsi_debug
& SHOWSCATGATH
)
/***********************************************\
* Set up the scatter gather block *
\***********************************************/
if(scsi_debug
& SHOWSCATGATH
)
printf("%d @0x%x:- ",xs
->datalen
,xs
->data
);
thisphys
= KVTOPHYS(thiskv
);
while ((datalen
) && (seg
< UHA_NSEG
))
/* put in the base address */
sg
->addr
.addr
[0] = (thisphys
& 0xff);
sg
->addr
.addr
[1] = ((thisphys
>> 8) & 0xff);
sg
->addr
.addr
[2] = ((thisphys
>> 16) & 0xff);
sg
->addr
.addr
[3] = ((thisphys
>> 24) & 0xff);
if(scsi_debug
& SHOWSCATGATH
)
/* do it at least once */
while ((datalen
) && (thisphys
== nextphys
))
/*********************************************\
* This page is contiguous (physically) with *
* the the last, just extend the length *
\*********************************************/
/* how far to the end of the page */
nextphys
= (thisphys
& (~(PAGESIZ
- 1)))
bytes_this_page
= nextphys
- thisphys
;
bytes_this_page
= min(bytes_this_page
bytes_this_seg
+= bytes_this_page
;
datalen
-= bytes_this_page
;
/* get more ready for the next page */
thiskv
= (thiskv
& (~(PAGESIZ
- 1)))
thisphys
= KVTOPHYS(thiskv
);
/********************************************\
* next page isn't contiguous, finish the seg *
\********************************************/
if(scsi_debug
& SHOWSCATGATH
)
printf("(0x%x)",bytes_this_seg
);
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);
sg
->len
.len
[3] = ((bytes_this_seg
>> 24) & 0xff);
templen
+= bytes_this_seg
;
} /*end of iov/kv decision */
mscp
->datalen
.len
[0] = (templen
& 0xff);
mscp
->datalen
.len
[1] = ((templen
>> 8) & 0xff);
mscp
->datalen
.len
[2] = ((templen
>> 16) & 0xff);
mscp
->datalen
.len
[3] = ((templen
>> 24) & 0xff);
if(scsi_debug
& SHOWSCATGATH
)
{ /* there's still data, must have run out of segs! */
printf("uha%d: uha_scsi_cmd, more than %d DMA segs\n",
xs
->error
= XS_DRIVER_STUFFUP
;
uha_free_mscp(unit
,mscp
,flags
);
{ /* No data xfer, use non S/G values */
mscp
->data
.addr
[0] = 0x00;
mscp
->data
.addr
[1] = 0x00;
mscp
->data
.addr
[2] = 0x00;
mscp
->data
.addr
[3] = 0x00;
mscp
->datalen
.len
[0] = 0x00;
mscp
->datalen
.len
[1] = 0x00;
mscp
->datalen
.len
[2] = 0x00;
mscp
->datalen
.len
[3] = 0x00;
/***********************************************\
* Put the scsi command in the mscp and start it *
\***********************************************/
bcopy(xs
->cmd
, mscp
->cdb
, xs
->cmdlen
);
/***********************************************\
* Usually return SUCCESSFULLY QUEUED *
\***********************************************/
if (!(flags
& SCSI_NOMASK
))
uha_send_mbox(unit
,mscp
);
timeout(uha_timeout
,mscp
,(xs
->timeout
* hz
) / 1000);
if(scsi_debug
& TRACEINTERRUPTS
)
return(SUCCESSFULLY_QUEUED
);
/***********************************************\
* If we can't use interrupts, poll on completion*
\***********************************************/
uha_send_mbox(unit
,mscp
);
if(scsi_debug
& TRACEINTERRUPTS
)
if(uha_poll(unit
,xs
->timeout
))
if (!(xs
->flags
& SCSI_SILENT
))
printf("uha%d: cmd fail\n",unit
);
if(!(uha_abort(unit
,mscp
)))
printf("uha%d: abort failed in wait\n",unit
);
uha_free_mscp(unit
,mscp
,flags
);
xs
->error
= XS_DRIVER_STUFFUP
;
} while (!(xs
->flags
& ITSDONE
));/* something (?) else finished */
uha_timeout(struct mscp
*mscp
)
int port
= uha_data
[unit
].baseport
;
unit
= mscp
->xs
->adapter
;
printf("uha%d:%d device timed out\n",unit
if(uha_debug
& UHA_SHOWMSCPS
)
uha_print_active_mscp(unit
);
if((uha_abort(unit
,mscp
) !=1) || (mscp
->flags
= MSCP_ABORTED
))
mscp
->xs
->retries
= 0; /* I MEAN IT ! */
uha_done(unit
,mscp
,FAIL
);
else /* abort the operation that has timed out */
timeout(uha_timeout
,mscp
,2 * hz
);
mscp
->flags
= MSCP_ABORTED
;
uha_show_scsi_cmd(struct scsi_xfer
*xs
)
u_char
*b
= (u_char
*)xs
->cmd
;
if(!(xs
->flags
& SCSI_RESET
))
printf("uha%d:%d:%d-RESET-\n"
printf("mscp:%x op:%x cmdlen:%d senlen:%d\n"
printf(" sg:%d sgnum:%x datlen:%d hstat:%x tstat:%x flags:%x\n"
uha_show_scsi_cmd(mscp
->xs
);
uha_print_active_mscp(int unit
)
struct mscp
*mscp
= uha_data
[unit
].mscps
;
if(mscp
->flags
!= MSCP_FREE
)