mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-16 10:20:30 +00:00
Add scsi target support.
This commit is contained in:
parent
8db34c841e
commit
bc0cfeb0ce
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=7819
@ -12,7 +12,7 @@
|
|||||||
* on the understanding that TFS is not responsible for the correct
|
* on the understanding that TFS is not responsible for the correct
|
||||||
* functioning of this software in any circumstances.
|
* functioning of this software in any circumstances.
|
||||||
*
|
*
|
||||||
* $Id: aha1542.c,v 1.42 1995/03/28 07:55:22 bde Exp $
|
* $Id: aha1542.c,v 1.43 1995/04/12 20:47:32 wollman Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -33,6 +33,7 @@
|
|||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <machine/clock.h>
|
#include <machine/clock.h>
|
||||||
#include <i386/isa/isa_device.h>
|
#include <i386/isa/isa_device.h>
|
||||||
|
#include <machine/clock.h>
|
||||||
#endif /* KERNEL */
|
#endif /* KERNEL */
|
||||||
#include <scsi/scsi_all.h>
|
#include <scsi/scsi_all.h>
|
||||||
#include <scsi/scsiconf.h>
|
#include <scsi/scsiconf.h>
|
||||||
@ -151,6 +152,8 @@ struct aha_mbx {
|
|||||||
#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
|
#define AHA_MBI_UNKNOWN 0x3 /* Tried to abort invalid CCB */
|
||||||
#define AHA_MBI_ERROR 0x4 /* Completed with error */
|
#define AHA_MBI_ERROR 0x4 /* Completed with error */
|
||||||
|
|
||||||
|
#define AHA_MBI_TGT_NO_CCB 0x10 /* Target received, no CCB ready */
|
||||||
|
|
||||||
/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
|
/* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
|
||||||
#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
|
#define AHA_NSEG 17 /* Number of scatter gather segments <= 16 */
|
||||||
/* allow 64 K i/o (min) */
|
/* allow 64 K i/o (min) */
|
||||||
@ -283,9 +286,7 @@ struct aha_extbios
|
|||||||
#define AHA_DMA_PAGES AHA_NSEG
|
#define AHA_DMA_PAGES AHA_NSEG
|
||||||
|
|
||||||
#define PAGESIZ 4096
|
#define PAGESIZ 4096
|
||||||
#define INVALIDATE_CACHE {asm volatile( ".byte 0x0F ;.byte 0x08" ); }
|
|
||||||
|
|
||||||
u_char aha_scratch_buf[256];
|
|
||||||
#ifdef AHADEBUG
|
#ifdef AHADEBUG
|
||||||
int aha_debug = 1;
|
int aha_debug = 1;
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
@ -305,6 +306,7 @@ struct aha_data {
|
|||||||
int aha_int; /* irq level */
|
int aha_int; /* irq level */
|
||||||
int aha_dma; /* DMA req channel */
|
int aha_dma; /* DMA req channel */
|
||||||
int aha_scsi_dev; /* scsi bus address */
|
int aha_scsi_dev; /* scsi bus address */
|
||||||
|
int flags;
|
||||||
|
|
||||||
/* We use different op codes for different revs of the board
|
/* We use different op codes for different revs of the board
|
||||||
* if we think residual codes will work.
|
* if we think residual codes will work.
|
||||||
@ -629,7 +631,7 @@ ahaattach(dev)
|
|||||||
aha->sc_link.adapter_targ = aha->aha_scsi_dev;
|
aha->sc_link.adapter_targ = aha->aha_scsi_dev;
|
||||||
aha->sc_link.adapter = &aha_switch;
|
aha->sc_link.adapter = &aha_switch;
|
||||||
aha->sc_link.device = &aha_dev;
|
aha->sc_link.device = &aha_dev;
|
||||||
aha->sc_link.flags = SDEV_BOUNCE;
|
aha->sc_link.flags = aha->flags;;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ask the adapter what subunits are present
|
* ask the adapter what subunits are present
|
||||||
@ -658,7 +660,6 @@ int
|
|||||||
ahaintr(unit)
|
ahaintr(unit)
|
||||||
int unit;
|
int unit;
|
||||||
{
|
{
|
||||||
struct aha_ccb *ccb;
|
|
||||||
unsigned char stat;
|
unsigned char stat;
|
||||||
register i;
|
register i;
|
||||||
struct aha_data *aha = ahadata[unit];
|
struct aha_data *aha = ahadata[unit];
|
||||||
@ -667,7 +668,7 @@ ahaintr(unit)
|
|||||||
printf("ahaintr ");
|
printf("ahaintr ");
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
/*
|
/*
|
||||||
* First acknowlege the interrupt, Then if it's not telling about
|
* First acknowledge the interrupt, Then if it's not telling about
|
||||||
* a completed operation just return.
|
* a completed operation just return.
|
||||||
*/
|
*/
|
||||||
stat = inb(AHA_INTR_PORT);
|
stat = inb(AHA_INTR_PORT);
|
||||||
@ -678,64 +679,95 @@ ahaintr(unit)
|
|||||||
printf("mbxin ");
|
printf("mbxin ");
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
/*
|
/*
|
||||||
* If it IS then process the competed operation
|
* If it IS then process the completed operation
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < AHA_MBX_SIZE; i++) {
|
for (i = 0; i < AHA_MBX_SIZE; i++) {
|
||||||
if (aha->aha_mbx.mbi[i].stat != AHA_MBI_FREE) {
|
struct aha_mbx_in *mbi = aha->aha_mbx.mbi + i;
|
||||||
ccb = (struct aha_ccb *) PHYSTOKV(
|
|
||||||
(scsi_3btou(aha->aha_mbx.mbi[i].ccb_addr)));
|
|
||||||
|
|
||||||
if ((stat = aha->aha_mbx.mbi[i].stat) != AHA_MBI_OK) {
|
if (mbi->stat != AHA_MBI_FREE) {
|
||||||
switch (stat) {
|
struct aha_ccb *ccb =
|
||||||
case AHA_MBI_ABORT:
|
(struct aha_ccb *)PHYSTOKV(scsi_3btou(mbi->ccb_addr));
|
||||||
|
|
||||||
|
stat = mbi->stat;
|
||||||
|
|
||||||
|
switch (stat) {
|
||||||
|
case AHA_MBI_OK:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AHA_MBI_ABORT:
|
||||||
#ifdef AHADEBUG
|
#ifdef AHADEBUG
|
||||||
if (aha_debug)
|
if (aha_debug)
|
||||||
printf("abort");
|
printf("abort");
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
ccb->host_stat = AHA_ABORTED;
|
ccb->host_stat = AHA_ABORTED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AHA_MBI_UNKNOWN:
|
case AHA_MBI_TGT_NO_CCB:
|
||||||
ccb = (struct aha_ccb *) 0;
|
/* We enabled target mode and received a SEND
|
||||||
|
* or RECEIVE command from the initiator, but
|
||||||
|
* we don't have any CCB registered to handle the command.
|
||||||
|
* At this point it would be nice to wakeup a
|
||||||
|
* process sleeping on this event via an ioctl,
|
||||||
|
* returning whether it is a SEND or RECEIVE and the
|
||||||
|
* required length.
|
||||||
|
* However, I want to look at the CAM documentation before
|
||||||
|
* I start extending the API at all.
|
||||||
|
*/
|
||||||
|
#ifdef NOISE_WHEN_TGT_NO_CDB
|
||||||
|
printf("Target received, but no CCB ready.\n");
|
||||||
|
printf("Initiator & lun: %02x\n", mbi->ccb_addr[0]);
|
||||||
|
printf("Max data length: %06x\n",
|
||||||
|
(mbi->ccb_addr[1] << 16) | (mbi->ccb_addr[2] << 8)
|
||||||
|
+ 255);
|
||||||
|
#endif
|
||||||
#ifdef AHADEBUG
|
#ifdef AHADEBUG
|
||||||
if (aha_debug)
|
if (aha_debug)
|
||||||
printf("unknown ccb for abort ");
|
printf("target-no-ccb");
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
/* may have missed it */
|
ccb = 0;
|
||||||
/* no such ccb known for abort */
|
break;
|
||||||
|
|
||||||
case AHA_MBI_ERROR:
|
case AHA_MBI_UNKNOWN:
|
||||||
break;
|
ccb = 0;
|
||||||
|
|
||||||
default:
|
|
||||||
panic("Impossible mbxi status");
|
|
||||||
|
|
||||||
}
|
|
||||||
#ifdef AHADEBUG
|
#ifdef AHADEBUG
|
||||||
if (aha_debug && ccb) {
|
if (aha_debug)
|
||||||
u_char *cp;
|
printf("unknown ccb for abort ");
|
||||||
cp = (u_char *) (&(ccb->scsi_cmd));
|
|
||||||
printf("op=%x %x %x %x %x %x\n",
|
|
||||||
cp[0], cp[1], cp[2],
|
|
||||||
cp[3], cp[4], cp[5]);
|
|
||||||
printf("stat %x for mbi[%d]\n"
|
|
||||||
,aha->aha_mbx.mbi[i].stat, i);
|
|
||||||
printf("addr = 0x%x\n", ccb);
|
|
||||||
}
|
|
||||||
#endif /*AHADEBUG */
|
#endif /*AHADEBUG */
|
||||||
|
/* may have missed it */
|
||||||
|
/* no such ccb known for abort */
|
||||||
|
|
||||||
|
case AHA_MBI_ERROR:
|
||||||
|
/* XXX ccb is still set up? Driver fails without it? */
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic("Impossible mbxi status");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#ifdef AHADEBUG
|
||||||
|
if (aha_debug && ccb && stat != AHA_MBI_OK) {
|
||||||
|
u_char *cp;
|
||||||
|
cp = (u_char *) (&(ccb->scsi_cmd));
|
||||||
|
printf("op=%x %x %x %x %x %x\n",
|
||||||
|
cp[0], cp[1], cp[2],
|
||||||
|
cp[3], cp[4], cp[5]);
|
||||||
|
printf("stat %x for mbi[%d]\n"
|
||||||
|
,mbi->stat, i);
|
||||||
|
printf("addr = 0x%x\n", ccb);
|
||||||
|
}
|
||||||
|
#endif /*AHADEBUG */
|
||||||
if (ccb) {
|
if (ccb) {
|
||||||
untimeout(aha_timeout, (caddr_t)ccb);
|
untimeout(aha_timeout, (caddr_t)ccb);
|
||||||
aha_done(unit, ccb);
|
aha_done(unit, ccb);
|
||||||
}
|
}
|
||||||
aha->aha_mbx.mbi[i].stat = AHA_MBI_FREE;
|
mbi->stat = AHA_MBI_FREE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A ccb (and hence a mbx-out is put onto the
|
* A ccb (and hence a mbx-out) is put onto the
|
||||||
* free list.
|
* free list.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@ -794,6 +826,38 @@ aha_get_ccb(unit, flags)
|
|||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
put_host_stat(int host_stat)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
struct { int host_stat; char *text; } tab[] = {
|
||||||
|
{ AHA_OK, "Cmd ok" },
|
||||||
|
{ AHA_LINK_OK, "Link cmd ok" },
|
||||||
|
{ AHA_LINK_IT, "Link cmd ok + int" },
|
||||||
|
{ AHA_SEL_TIMEOUT, "Selection time out" },
|
||||||
|
{ AHA_OVER_UNDER, "Data over/under run" },
|
||||||
|
{ AHA_BUS_FREE, "Bus dropped at unexpected time" },
|
||||||
|
{ AHA_INV_BUS, "Invalid bus phase/sequence" },
|
||||||
|
{ AHA_BAD_MBO, "Incorrect MBO cmd" },
|
||||||
|
{ AHA_BAD_CCB, "Incorrect ccb opcode" },
|
||||||
|
{ AHA_BAD_LINK, "Not same values of LUN for links" },
|
||||||
|
{ AHA_INV_TARGET, "Invalid target direction" },
|
||||||
|
{ AHA_CCB_DUP, "Duplicate CCB received" },
|
||||||
|
{ AHA_INV_CCB, "Invalid CCB or segment list" },
|
||||||
|
{ AHA_ABORTED, "Software abort" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(tab) / sizeof(tab[0]); i++) {
|
||||||
|
if (tab[i].host_stat == host_stat) {
|
||||||
|
printf("%s\n", tab[i].text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Unknown host_stat %02x\n", host_stat);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a ccb which has been processed by the
|
* We have a ccb which has been processed by the
|
||||||
* adaptor, now we look to see how the operation
|
* adaptor, now we look to see how the operation
|
||||||
@ -842,6 +906,7 @@ aha_done(unit, ccb)
|
|||||||
{
|
{
|
||||||
case AHA_TARGET_CCB:
|
case AHA_TARGET_CCB:
|
||||||
xs->resid = xs->datalen - scsi_3btoi(ccb->data_length);
|
xs->resid = xs->datalen - scsi_3btoi(ccb->data_length);
|
||||||
|
xs->flags |= SCSI_RESID_VALID;
|
||||||
if (xs->resid <= 0)
|
if (xs->resid <= 0)
|
||||||
xs->error = XS_LENGTH;
|
xs->error = XS_LENGTH;
|
||||||
break;
|
break;
|
||||||
@ -849,11 +914,9 @@ aha_done(unit, ccb)
|
|||||||
case AHA_INIT_RESID_CCB:
|
case AHA_INIT_RESID_CCB:
|
||||||
case AHA_INIT_SG_RESID_CCB:
|
case AHA_INIT_SG_RESID_CCB:
|
||||||
xs->resid = scsi_3btoi(ccb->data_length);
|
xs->resid = scsi_3btoi(ccb->data_length);
|
||||||
|
xs->flags |= SCSI_RESID_VALID;
|
||||||
if (xs->resid <= 0)
|
if (xs->resid <= 0)
|
||||||
xs->error = XS_LENGTH;
|
xs->error = XS_LENGTH;
|
||||||
printf("aha over under: resid %d error %d.\n",
|
|
||||||
xs->resid, xs->error);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -863,8 +926,8 @@ aha_done(unit, ccb)
|
|||||||
|
|
||||||
default: /* Other scsi protocol messes */
|
default: /* Other scsi protocol messes */
|
||||||
xs->error = XS_DRIVER_STUFFUP;
|
xs->error = XS_DRIVER_STUFFUP;
|
||||||
printf("aha%d:host_stat%x\n",
|
printf("aha%d: ", unit);
|
||||||
unit, ccb->host_stat);
|
put_host_stat(ccb->host_stat);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
|
SC_DEBUG(xs->sc_link, SDEV_DB3, ("target err 0x%x\n",
|
||||||
@ -891,6 +954,21 @@ aha_done(unit, ccb)
|
|||||||
scsi_done(xs);
|
scsi_done(xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *board_rev(int type)
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 0x20: return "Buslogic 545?";
|
||||||
|
case 0x31: return "AHA-1540";
|
||||||
|
case 0x41: return "AHA-154x[AB]";
|
||||||
|
case 0x42: return "AHA-1640";
|
||||||
|
case 0x43: return "AHA-1542C";
|
||||||
|
case 0x44: return "AHA-1542CF";
|
||||||
|
case 0x45: return "AHA-1542CF BIOS v2.01";
|
||||||
|
default: return "Unknown board";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start the board, ready for normal operation
|
* Start the board, ready for normal operation
|
||||||
*/
|
*/
|
||||||
@ -978,6 +1056,8 @@ aha_init(unit)
|
|||||||
inquire.revision_1, inquire.revision_2);
|
inquire.revision_1, inquire.revision_2);
|
||||||
#endif /* AHADEBUG */
|
#endif /* AHADEBUG */
|
||||||
|
|
||||||
|
aha->flags = SDEV_BOUNCE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are a 1542C or 1542CF disable the extended bios so that the
|
* If we are a 1542C or 1542CF disable the extended bios so that the
|
||||||
* mailbox interface is unlocked.
|
* mailbox interface is unlocked.
|
||||||
@ -986,36 +1066,58 @@ aha_init(unit)
|
|||||||
* No need to check the extended bios flags as some of the
|
* No need to check the extended bios flags as some of the
|
||||||
* extensions that cause us problems are not flagged in that byte.
|
* extensions that cause us problems are not flagged in that byte.
|
||||||
*/
|
*/
|
||||||
|
printf("aha%d: %s-V%c.%c",
|
||||||
|
unit, board_rev(inquire.boardid), inquire.revision_1,
|
||||||
|
inquire.revision_2);
|
||||||
|
|
||||||
if ((inquire.boardid == 0x43) || (inquire.boardid == 0x44) ||
|
if ((inquire.boardid == 0x43) || (inquire.boardid == 0x44) ||
|
||||||
(inquire.boardid == 0x45) || (inquire.boardid == 0x41
|
(inquire.boardid == 0x45) || (inquire.boardid == 0x41
|
||||||
&& inquire.revision_1 == 0x31 && inquire.revision_2 == 0x34)) {
|
&& inquire.revision_1 == 0x31 && inquire.revision_2 == 0x34)) {
|
||||||
static char *revs[] =
|
|
||||||
{"154xB-3.2", "1640", "154xC", "154xCF", "154xCF-2.01"};
|
|
||||||
aha_cmd(unit, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
|
aha_cmd(unit, 0, sizeof(extbios), 0, &extbios, AHA_EXT_BIOS);
|
||||||
#ifdef AHADEBUG
|
#ifdef AHADEBUG
|
||||||
printf("aha%d: extended bios flags %x\n", unit, extbios.flags);
|
printf("aha%d: extended bios flags %x\n", unit, extbios.flags);
|
||||||
#endif /* AHADEBUG */
|
#endif /* AHADEBUG */
|
||||||
|
|
||||||
/* Say exactly what we think this is in case we ever get rev
|
printf(", enabling mailbox");
|
||||||
* dependent problems:
|
|
||||||
*/
|
|
||||||
printf("aha%d is a %s-V%c.%c: enabling mailbox and residuals\n",
|
|
||||||
unit, revs[inquire.boardid - 0x41], inquire.revision_1,
|
|
||||||
inquire.revision_2);
|
|
||||||
aha_cmd(unit, 2, 0, 0, 0, AHA_MBX_ENABLE,
|
aha_cmd(unit, 2, 0, 0, 0, AHA_MBX_ENABLE,
|
||||||
0, extbios.mailboxlock);
|
0, extbios.mailboxlock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Which boards support residuals? Some early 1542A's apparently
|
||||||
|
* don't. The 1542B with V0.5 of the software does, so I've
|
||||||
|
* arbitrarily set that as the earliest rev.
|
||||||
|
*/
|
||||||
|
if ((inquire.boardid == 0x43) || (inquire.boardid == 0x44) ||
|
||||||
|
(inquire.boardid == 0x45) || (inquire.boardid == 0x41
|
||||||
|
&& (inquire.revision_1 > '0' || inquire.revision_2 >= '5'))) {
|
||||||
|
printf(", enabling residuals");
|
||||||
aha->init_opcode = AHA_INIT_RESID_CCB;
|
aha->init_opcode = AHA_INIT_RESID_CCB;
|
||||||
aha->sg_opcode = AHA_INIT_SG_RESID_CCB;
|
aha->sg_opcode = AHA_INIT_SG_RESID_CCB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Which boards support target operations? The 1542C completely
|
||||||
|
* locks up the SCSI bus if you enable them. I'm only sure
|
||||||
|
* about the B.
|
||||||
|
*/
|
||||||
|
if (inquire.boardid == 0x41) {
|
||||||
|
printf(", target ops");
|
||||||
|
aha->flags |= SDEV_TARGET_OPS;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setup dma channel from jumpers and save int
|
* setup dma channel from jumpers and save int
|
||||||
* level
|
* level
|
||||||
*/
|
*/
|
||||||
printf("aha%d: reading board settings, ", unit);
|
printf("aha%d: reading board settings, ", unit);
|
||||||
#define PRNT(x) printf(x)
|
#define PRNT(x) printf(x)
|
||||||
DELAY(1000); /* for Bustek 545 */
|
if (inquire.boardid == 0x20) {
|
||||||
|
DELAY(1000); /* for Bustek 545 */
|
||||||
|
}
|
||||||
|
|
||||||
aha_cmd(unit, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
|
aha_cmd(unit, 0, sizeof(conf), 0, &conf, AHA_CONF_GET);
|
||||||
switch (conf.chan) {
|
switch (conf.chan) {
|
||||||
case CHAN0:
|
case CHAN0:
|
||||||
@ -1136,6 +1238,91 @@ ahaminphys(bp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int aha_escape(xs, ccb)
|
||||||
|
struct scsi_xfer *xs;
|
||||||
|
struct aha_ccb *ccb;
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
if (xs->cmd)
|
||||||
|
{
|
||||||
|
switch(xs->cmd->opcode)
|
||||||
|
{
|
||||||
|
case SCSI_OP_RESET:
|
||||||
|
ccb->opcode = AHA_RESET_CCB;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SCSI_OP_TARGET:
|
||||||
|
s= splbio();
|
||||||
|
aha_cmd(xs->sc_link->adapter_unit, 2, 0, 0, 0, AHA_TARGET_EN,
|
||||||
|
(int)xs->cmd->bytes[0], (int)1);
|
||||||
|
splx(s);
|
||||||
|
ret = COMPLETE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = ESCAPE_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ccb->opcode = AHA_RESET_CCB;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define physdb(ARG) (void)(ARG)
|
||||||
|
|
||||||
|
/* physcontig: Scan forward from a KV and return length to the
|
||||||
|
* end of physically contiguous addresses. This belongs in
|
||||||
|
* i386/.../something_or_other.c
|
||||||
|
* XXX: Find the right thing in the kernel.
|
||||||
|
*/
|
||||||
|
static int physcontig(int kv, int len)
|
||||||
|
{
|
||||||
|
int len_was = len;
|
||||||
|
u_long kvl = (u_long)kv;
|
||||||
|
|
||||||
|
int phys_len;
|
||||||
|
u_long phys, prev_phys;
|
||||||
|
|
||||||
|
prev_phys = KVTOPHYS(kvl);
|
||||||
|
|
||||||
|
/* We go at least to the end of this page:
|
||||||
|
*/
|
||||||
|
phys_len = PAGESIZ - (prev_phys & (PAGESIZ - 1));
|
||||||
|
len -= phys_len;
|
||||||
|
kvl += phys_len;
|
||||||
|
prev_phys &= ~(PAGESIZ - 1);
|
||||||
|
|
||||||
|
while (len > 0)
|
||||||
|
{
|
||||||
|
phys = KVTOPHYS(kvl);
|
||||||
|
|
||||||
|
if (phys != prev_phys + PAGESIZ)
|
||||||
|
{
|
||||||
|
physdb(("phys %08x != prev_phys %08x + PAGESIZ\n",
|
||||||
|
phys, prev_phys));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_phys = phys;
|
||||||
|
kvl += PAGESIZ;
|
||||||
|
len -= PAGESIZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
phys_len = (len < 0) ? len_was : (len_was - len);
|
||||||
|
|
||||||
|
physdb(("physcontig(%08x, %d) = %d\n", kv, len_was, phys_len));
|
||||||
|
|
||||||
|
return phys_len;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* start a scsi operation given the command and
|
* start a scsi operation given the command and
|
||||||
* the data address. Also needs the unit, target
|
* the data address. Also needs the unit, target
|
||||||
@ -1193,16 +1380,87 @@ aha_scsi_cmd(xs)
|
|||||||
* fall on the ground if you ask for anything but
|
* fall on the ground if you ask for anything but
|
||||||
* an exact number of sense bytes (wiping out the
|
* an exact number of sense bytes (wiping out the
|
||||||
* sense data)
|
* sense data)
|
||||||
|
* XXX: This was lost at some point in scsi_ioctl.c.
|
||||||
*/
|
*/
|
||||||
ccb->req_sense_length = (xs->req_sense_length)
|
ccb->req_sense_length = (xs->req_sense_length)
|
||||||
? xs->req_sense_length
|
? xs->req_sense_length
|
||||||
: sizeof(ccb->scsi_sense);
|
: sizeof(ccb->scsi_sense);
|
||||||
|
|
||||||
if ((xs->datalen) && (!(flags & SCSI_RESET))) {
|
/* XXX: I propose we move the reset handling into the escape
|
||||||
/* can use S/G only if not zero length */
|
* handling.
|
||||||
scsi_uto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
|
*/
|
||||||
sg = ccb->scat_gath;
|
if (flags & SCSI_RESET) {
|
||||||
seg = 0;
|
flags |= SCSI_ESCAPE;
|
||||||
|
xs->cmd->opcode = SCSI_OP_RESET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up the CCB. For an escape function, the escape hook may
|
||||||
|
* set it up for us.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (flags & SCSI_ESCAPE) {
|
||||||
|
int ret;
|
||||||
|
ret = aha_escape(xs, ccb);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else if (flags & SCSI_TARGET)
|
||||||
|
{
|
||||||
|
ccb->opcode = AHA_TARGET_CCB;
|
||||||
|
|
||||||
|
/* These must be set up for target mode:
|
||||||
|
*/
|
||||||
|
if (flags & SCSI_DATA_IN)
|
||||||
|
ccb->data_in = 1;
|
||||||
|
if (flags & SCSI_DATA_OUT)
|
||||||
|
ccb->data_out = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ccb->opcode = (xs->datalen? /* can't use S/G if zero length */
|
||||||
|
AHA_INIT_SCAT_GATH_CCB
|
||||||
|
:AHA_INITIATOR_CCB);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ccb->opcode)
|
||||||
|
{
|
||||||
|
case AHA_TARGET_CCB:
|
||||||
|
if (xs->data)
|
||||||
|
scsi_uto3b(KVTOPHYS((int)xs->data), ccb->data_addr);
|
||||||
|
else
|
||||||
|
scsi_uto3b(0, ccb->data_addr);
|
||||||
|
|
||||||
|
/* For non scatter-gather I/O (and Target mode doesn't do
|
||||||
|
* scatter-gather) we need to truncate the transfer
|
||||||
|
* at the first non consecutive physical address.
|
||||||
|
*/
|
||||||
|
scsi_uto3b(physcontig((int)xs->data, xs->datalen), ccb->data_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* This should be folded in with TARGET_CCB once
|
||||||
|
* physcontig is debugged.
|
||||||
|
*/
|
||||||
|
case AHA_INITIATOR_CCB:
|
||||||
|
case AHA_INIT_RESID_CCB:
|
||||||
|
|
||||||
|
if (xs->data)
|
||||||
|
scsi_uto3b(KVTOPHYS((int)xs->data), ccb->data_addr);
|
||||||
|
else
|
||||||
|
scsi_uto3b(0, ccb->data_addr);
|
||||||
|
|
||||||
|
scsi_uto3b(xs->datalen, ccb->data_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AHA_RESET_CCB:
|
||||||
|
scsi_uto3b(0, ccb->data_addr);
|
||||||
|
scsi_uto3b(0, ccb->data_length);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AHA_INIT_SCAT_GATH_CCB:
|
||||||
|
case AHA_INIT_SG_RESID_CCB:
|
||||||
|
scsi_uto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr );
|
||||||
|
sg = ccb->scat_gath ;
|
||||||
|
seg = 0;
|
||||||
#ifdef TFS_ONLY
|
#ifdef TFS_ONLY
|
||||||
if (flags & SCSI_DATA_UIO) {
|
if (flags & SCSI_DATA_UIO) {
|
||||||
iovp = ((struct uio *) xs->data)->uio_iov;
|
iovp = ((struct uio *) xs->data)->uio_iov;
|
||||||
@ -1226,7 +1484,7 @@ aha_scsi_cmd(xs)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
SC_DEBUG(xs->sc_link, SDEV_DB4,
|
SC_DEBUG(xs->sc_link, SDEV_DB4,
|
||||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
("%ld @%p:- ", xs->datalen, xs->data));
|
||||||
datalen = xs->datalen;
|
datalen = xs->datalen;
|
||||||
thiskv = (int) xs->data;
|
thiskv = (int) xs->data;
|
||||||
thisphys = KVTOPHYS(thiskv);
|
thisphys = KVTOPHYS(thiskv);
|
||||||
@ -1293,15 +1551,20 @@ aha_scsi_cmd(xs)
|
|||||||
aha_free_ccb(unit, ccb, flags);
|
aha_free_ccb(unit, ccb, flags);
|
||||||
return (HAD_ERROR);
|
return (HAD_ERROR);
|
||||||
}
|
}
|
||||||
} else { /* No data xfer, use non S/G values */
|
break;
|
||||||
scsi_uto3b(0, ccb->data_addr);
|
|
||||||
scsi_uto3b(0, ccb->data_length);
|
default:
|
||||||
|
printf("aha_scsi_cmd%d: Illegal CCB opcode.\n", unit);
|
||||||
|
xs->error = XS_DRIVER_STUFFUP;
|
||||||
|
aha_free_ccb(unit,ccb,flags);
|
||||||
|
return HAD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
scsi_uto3b(0, ccb->link_addr);
|
scsi_uto3b(0, ccb->link_addr);
|
||||||
/*
|
/*
|
||||||
* Put the scsi command in the ccb and start it
|
* Put the scsi command in the ccb and start it
|
||||||
*/
|
*/
|
||||||
if (!(flags & SCSI_RESET))
|
if (!(flags & SCSI_ESCAPE))
|
||||||
bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
|
bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmd_length);
|
||||||
if (!(flags & SCSI_NOMASK)) {
|
if (!(flags & SCSI_NOMASK)) {
|
||||||
s = splbio(); /* stop instant timeouts */
|
s = splbio(); /* stop instant timeouts */
|
||||||
@ -1469,6 +1732,8 @@ aha_set_bus_speed(unit)
|
|||||||
*/
|
*/
|
||||||
static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
|
static char aha_test_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz!@";
|
||||||
|
|
||||||
|
u_char aha_scratch_buf[256];
|
||||||
|
|
||||||
int
|
int
|
||||||
aha_bus_speed_check(unit, speed)
|
aha_bus_speed_check(unit, speed)
|
||||||
int unit, speed;
|
int unit, speed;
|
||||||
|
Loading…
Reference in New Issue
Block a user