## diffname port/devscsi.c 1991/0110
## diff -e /dev/null /n/bootesdump/1991/0110/sys/src/9/68020/devscsi.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "errno.h"
#include "devtab.h"
#include "io.h"
#include "port.h"
#include "scsi.h"
int scsiintr(void);
#define DPRINT if(debug)kprint
enum {
Qdir, Qcmd, Qdata, Qdebug,
};
static Dirtab scsidir[]={
"cmd", {Qcmd}, 0, 0600,
"data", {Qdata}, 0, 0600,
"debug", {Qdebug}, 1, 0600,
};
#define NSCSI (sizeof scsidir/sizeof(Dirtab))
static Scsi staticcmd; /* BUG */
static uchar datablk[8192]; /* BUG */
static int debugs[8];
static int isscsi;
static int ownid = 0x08|7; /* enable advanced features */
static int
scsigen1(Chan *c, long qid, Dir *dp)
{
if (qid == CHDIR)
devdir(c, (Qid){qid,0}, ".", 0, 0500, dp);
else if (qid == 1)
devdir(c, (Qid){qid,0}, "id", 1, 0600, dp);
else if (qid&CHDIR) {
char name[2];
name[0] = '0'+((qid>>4)&7), name[1] = 0;
devdir(c, (Qid){qid,0}, name, 0, 0500, dp);
} else {
Dirtab *tab = &scsidir[(qid&7)-1];
devdir(c, (Qid){qid,0}, tab->name, tab->length, tab->perm, dp);
}
return 1;
}
static int
scsigeno(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
{
return scsigen1(c, c->qid.path, dp);
}
static int
scsigen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dp)
{
if (c->qid.path == CHDIR) {
if (0<=s && s<=7)
return scsigen1(c, CHDIR|0x100|(s<<4), dp);
else if (s == 8)
return scsigen1(c, 1, dp);
else
return -1;
}
if (s >= NSCSI)
return -1;
return scsigen1(c, (c->qid.path&~CHDIR)+s+1, dp);
}
void
scsireset(void)
{
addportintr(scsiintr);
}
Chan *
scsiattach(char *param)
{
return devattach('S', param);
}
Chan *
scsiclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
scsiwalk(Chan *c, char *name)
{
return devwalk(c, name, 0, 0, scsigen);
}
void
scsistat(Chan *c, char *db)
{
devstat(c, db, 0, 0, scsigen);
}
Chan *
scsiopen(Chan *c, int omode)
{
return devopen(c, omode, 0, 0, scsigeno);
}
void
scsicreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
scsiclose(Chan *c)
{}
long
scsiread(Chan *c, char *a, long n)
{
Scsi *cmd = &staticcmd;
if (n == 0)
return 0;
if(c->qid.path & CHDIR)
return devdirread(c, a, n, 0, 0, scsigen);
if(c->qid.path==1){
if(c->offset == 0){
*a = ownid;
n = 1;
}else
n = 0;
}else switch((int)(c->qid.path & 0xf)){
case Qcmd:
if (n < 4)
error(Ebadarg);
/*if(canqlock(cmd)){
qunlock(cmd);
error(Egreg);
}*/
n = 4;
*a++ = cmd->state>>8; *a++ = cmd->state;
*a++ = cmd->status>>8; *a = cmd->status;
/*qunlock(cmd);*/
break;
case Qdata:
if (n > sizeof datablk)
error(Ebadarg);
cmd->data.base = datablk;
cmd->data.lim = cmd->data.base + n;
cmd->data.ptr = cmd->data.base;
cmd->save = cmd->data.base;
scsiexec(cmd, 1);
n = cmd->data.ptr - cmd->data.base;
memcpy(a, cmd->data.base, n);
break;
case Qdebug:
if (c->offset == 0) {
n=1;
*a="01"[debugs[(c->qid.path>>4)&7]!=0];
} else
n = 0;
break;
default:
panic("scsiread");
}
return n;
}
long
scsiwrite(Chan *c, char *a, long n)
{
Scsi *cmd = &staticcmd;
if(c->qid.path==1 && n>0){
if(c->offset == 0){
n = 1;
ownid=*a;
scsiinit();
}else
n = 0;
}else switch ((int)c->qid.path & 0xf){
case Qcmd:
if (n < 6 || n > sizeof cmd->cmdblk)
error(Ebadarg);
/*qlock(cmd);*/
cmd->cmd.base = cmd->cmdblk;
memcpy(cmd->cmd.base, a, n);
cmd->cmd.lim = cmd->cmd.base + n;
cmd->cmd.ptr = cmd->cmd.base;
cmd->target = (c->qid.path>>4)&7;
cmd->lun = (a[1]>>5)&7;
cmd->state = 0;
cmd->status = 0xFFFF;
break;
case Qdata:
if (n > sizeof datablk)
error(Ebadarg);
cmd->data.base = datablk;
cmd->data.lim = cmd->data.base + n;
cmd->data.ptr = cmd->data.base;
cmd->save = cmd->data.base;
memcpy(cmd->data.base, a, n);
scsiexec(cmd, 0);
n = cmd->data.ptr - cmd->data.base;
break;
case Qdebug:
if (c->offset == 0) {
debugs[(c->qid.path>>4)&7] = (*a=='1');
n = 1;
} else
n = 0;
break;
default:
panic("scsiwrite");
}
return n;
}
void
scsiremove(Chan *c)
{
error(Eperm);
}
void
scsiwstat(Chan *c, char *dp)
{
error(Eperm);
}
void
scsicmd(Scsi *cmd, int dev, int cmdbyte, uchar *buf, long size)
{
qlock(cmd);
cmd->target = dev>>3;
cmd->lun = dev&7;
cmd->cmd.base = cmd->cmdblk;
cmd->data.base = buf;
cmd->cmd.ptr = cmd->cmd.base;
memset(cmd->cmdblk, 0, sizeof cmd->cmdblk);
cmd->cmdblk[0] = cmdbyte;
switch (cmdbyte>>5) {
case 0:
cmd->cmd.lim = &cmd->cmdblk[6]; break;
case 1:
cmd->cmd.lim = &cmd->cmdblk[10]; break;
default:
cmd->cmd.lim = &cmd->cmdblk[12]; break;
}
switch (cmdbyte) {
case 0x00: /* test unit ready */
break;
case 0x03: /* read sense data */
cmd->cmdblk[4] = size;
break;
case 0x25: /* read capacity */
break;
}
cmd->data.lim = cmd->data.base + size;
cmd->data.ptr = cmd->data.base;
cmd->save = cmd->data.base;
}
int
scsiready(int dev)
{
static Scsi cmd;
int status;
scsicmd(&cmd, dev, 0x00, 0, 0);
status = scsiexec(&cmd, 0);
qunlock(&cmd);
if ((status&0xff00) != 0x6000)
error(Eio);
return status&0xff;
}
int
scsisense(int dev, uchar *p)
{
static Scsi cmd;
static uchar buf[18];
int status;
scsicmd(&cmd, dev, 0x03, buf, sizeof buf);
status = scsiexec(&cmd, 1);
memcpy(p, buf, sizeof buf);
qunlock(&cmd);
if ((status&0xff00) != 0x6000)
error(Eio);
return status&0xff;
}
int
scsicap(int dev, uchar *p)
{
static Scsi cmd;
static uchar buf[8];
int status;
scsicmd(&cmd, dev, 0x25, buf, sizeof buf);
status = scsiexec(&cmd, 1);
memcpy(p, buf, sizeof buf);
qunlock(&cmd);
if ((status&0xff00) != 0x6000)
error(Eio);
return status&0xff;
}
typedef struct Scsictl {
uchar asr;
uchar data;
uchar stat;
uchar dma;
} Scsictl;
#define Scsiaddr 48
#define DEV ((Scsictl *)&PORT[Scsiaddr])
static long poot;
#define WAIT (poot=0, (poot==0?0:poot))
#define PUT(a,d) (DEV->asr=(a), WAIT, DEV->data=(d))
#define GET(a) (DEV->asr=(a), WAIT, DEV->data)
enum Int_status {
Inten = 0x01, Scsirst = 0x02,
INTRQ = 0x01, DMA = 0x02,
};
enum SBIC_regs {
Own_id=0x00, Control=0x01, CDB=0x03, Target_LUN=0x0f,
Cmd_phase=0x10, Tc_hi=0x12,
Dest_id=0x15, Src_id=0x16, SCSI_Status=0x17,
Cmd=0x18, Data=0x19,
};
enum Commands {
Reset = 0x00,
Assert_ATN = 0x02,
Negate_ACK = 0x03,
Select_with_ATN = 0x06,
Select_with_ATN_and_Xfr = 0x08,
Select_and_Xfr = 0x09,
Transfer_Info = 0x20,
SBT = 0x80, /* modifier for single-byte transfer */
};
enum Aux_status {
INT=0x80, LCI=0x40, BSY=0x20, CIP=0x10,
PE=0x02, DBR=0x01,
};
static QLock scsilock;
static Rendez scsirendez;
static uchar *datap;
static long debug, scsirflag, scsibusy, scsiinservice;
static void
nop(void)
{}
static int
scsidone(void *arg)
{
return (scsibusy == 0);
}
int
scsiexec(Scsi *p, int rflag)
{
long n;
debug = debugs[p->target&7];
DPRINT("scsi %d.%d ", p->target, p->lun);
qlock(&scsilock);
if(waserror()){
qunlock(&scsilock);
nexterror();
}
scsirflag = rflag;
datap = p->data.base;
if ((ownid & 0x08) && rflag)
PUT(Dest_id, 0x40|p->target);
else
PUT(Dest_id, p->target);
PUT(Target_LUN, p->lun);
n = p->data.lim - p->data.base;
PUT(Tc_hi, n>>16);
DEV->data = n>>8;
DEV->data = n;
if (ownid & 0x08) {
n = p->cmd.lim - p->cmd.ptr;
DPRINT("len=%d ", n);
PUT(Own_id, n);
}
PUT(CDB, *(p->cmd.ptr)++);
while (p->cmd.ptr < p->cmd.lim)
DEV->data = *(p->cmd.ptr)++;
scsibusy = 1;
PUT(Cmd, Select_and_Xfr);
DPRINT("S<");
sleep(&scsirendez, scsidone, 0);
DPRINT(">");
p->data.ptr = datap;
p->status = GET(Target_LUN);
p->status |= DEV->data<<8;
poperror();
qunlock(&scsilock);
debug = 0;
return p->status;
}
void
scsirun(void)
{
wakeup(&scsirendez);
scsibusy = 0;
}
void
scsiinit(void)
{
isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L);
if (isscsi >= 0) {
DEV->stat = Scsirst;
WAIT; nop(); WAIT;
DEV->stat = Inten;
while (DEV->stat & (INTRQ|DMA))
nop();
ownid &= 0x0f; /* possibly advanced features */
ownid |= 0x80; /* 16MHz */
PUT(Own_id, ownid);
PUT(Cmd, Reset);
}
}
void
scsireset0(void)
{
PUT(Control, 0x29); /* burst DMA, halt on parity error */
PUT(Control+1, 0xff); /* timeout */
PUT(Src_id, 0x80); /* enable reselection */
scsirun();
/*qunlock(&scsilock);*/
}
int
scsiintr(void)
{
int status, s;
if (isscsi < 0 || scsiinservice
|| !((status = DEV->stat) & (DMA|INTRQ)))
return 0;
DEV->stat = 0;
scsiinservice = 1;
s = spl1();
DPRINT("i%x ", status);
do {
if (status & DMA)
scsidmaintr();
if (status & INTRQ)
scsictrlintr();
} while ((status = DEV->stat) & (DMA|INTRQ));
splx(s);
scsiinservice = 0;
DEV->stat = Inten;
return 1;
}
void
scsidmaintr(void)
{
uchar *p=0;
/*
* if (scsirflag) {
* unsigned char *p;
* DPRINT("R", p=datap);
* do
* *datap++ = DEV->dma;
* while (DEV->stat & DMA);
* DPRINT("%d ", datap-p);
* } else {
* unsigned char *p;
* DPRINT("W", p=datap);
* do
* DEV->dma = *datap++;
* while (DEV->stat & DMA);
* DPRINT("%d ", datap-p);
* }
*/
if (scsirflag) {
DPRINT("R", p=datap);
datap = scsirecv(datap);
DPRINT("%d ", datap-p);
} else {
DPRINT("X", p=datap);
datap = scsixmit(datap);
DPRINT("%d ", datap-p);
}
}
void
scsictrlintr(void)
{
int status;
status = GET(SCSI_Status);
DPRINT("I%2.2x ", status);
switch(status){
case 0x00: /* reset by command or power-up */
case 0x01: /* reset by command or power-up */
scsireset0();
break;
case 0x21: /* Save Data Pointers message received */
break;
case 0x16: /* select-and-transfer completed */
case 0x42: /* timeout during select */
scsirun();
break;
case 0x4b: /* unexpected status phase */
PUT(Tc_hi, 0);
DEV->data = 0;
DEV->data = 0;
PUT(Cmd_phase, 0x46);
PUT(Cmd, Select_and_Xfr);
break;
default:
kprint("scsintr 0x%ux\n", status);
DEV->asr = Target_LUN;
kprint("lun/status 0x%ux\n", DEV->data);
kprint("phase 0x%ux\n", DEV->data);
switch (status&0xf0) {
case 0x00:
case 0x10:
case 0x20:
case 0x40:
case 0x80:
if (status & 0x08) {
kprint("count 0x%ux", GET(Tc_hi));
kprint(" 0x%ux", DEV->data);
kprint(" 0x%ux\n", DEV->data);
}
scsirun();
break;
default:
panic("scsi status 0x%2.2ux", status);
}
}
}
.
## diffname port/devscsi.c 1991/0112
## diff -e /n/bootesdump/1991/0110/sys/src/9/68020/devscsi.c /n/bootesdump/1991/0112/sys/src/9/68020/devscsi.c
473c
uchar *p = 0;
.
321c
#define WAIT (poot=0, poot==0?0:poot)
.
## diffname port/devscsi.c 1991/0115
## diff -e /n/bootesdump/1991/0112/sys/src/9/68020/devscsi.c /n/bootesdump/1991/0115/sys/src/9/68020/devscsi.c
10,12d
## diffname port/devscsi.c 1991/0318
## diff -e /n/bootesdump/1991/0201/sys/src/9/68020/devscsi.c /n/bootesdump/1991/0318/sys/src/9/gnot/devscsi.c
300c
memmove(p, buf, sizeof buf);
.
285c
memmove(p, buf, sizeof buf);
.
202c
memmove(cmd->data.base, a, n);
.
187c
memmove(cmd->cmd.base, a, n);
.
155c
memmove(a, cmd->data.base, n);
.
## diffname port/devscsi.c 1991/0411
## diff -e /n/bootesdump/1991/0318/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0411/sys/src/9/gnot/devscsi.c
207c
if (offset == 0) {
.
175c
if(offset == 0){
.
171c
scsiwrite(Chan *c, char *a, long n, ulong offset)
.
158c
if (offset == 0) {
.
128c
if(offset == 0){
.
120c
scsiread(Chan *c, char *a, long n, ulong offset)
.
## diffname port/devscsi.c 1991/0419
## diff -e /n/bootesdump/1991/0411/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0419/sys/src/9/gnot/devscsi.c
96a
Chan*
scsiclwalk(Chan *c, char *name)
{
return devclwalk(c, name);
}
.
## diffname port/devscsi.c 1991/0423
## diff -e /n/bootesdump/1991/0419/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0423/sys/src/9/gnot/devscsi.c
383a
p->rflag = rflag;
.
304,307c
status = scsiexec(cmd, 1);
memmove(p, cmd->data.base, 8);
qunlock(cmd);
.
301,302c
Scsi *cmd = scsicmd(dev, 0x25, 8);
.
299c
scsicap(int dev, void *p)
.
289,292c
status = scsiexec(cmd, 1);
memmove(p, cmd->data.base, 18);
qunlock(cmd);
.
286,287c
Scsi *cmd = scsicmd(dev, 0x03, 18);
.
284c
scsisense(int dev, void *p)
.
275,277c
status = scsiexec(cmd, 0);
qunlock(cmd);
.
273c
Scsi *cmd = scsicmd(dev, 0x00, 0);
.
267a
return cmd;
.
264a
cmd->data.base = datablk;
.
256c
switch(cmdbyte){
.
248c
switch(cmdbyte>>5){
.
244d
239a
Scsi *cmd = &staticcmd;
if(size > DATASIZE)
panic("scsicmd %d", size);
.
237,238c
Scsi *
scsicmd(int dev, int cmdbyte, long size)
.
202c
if(canqlock(cmd)){
qunlock(cmd);
error(Egreg);
}
if(cmd->pid != u->p->pid)
error(Egreg);
if (n > DATASIZE)
.
198d
191c
qlock(cmd);
cmd->pid = u->p->pid;
.
184c
scsireset();
.
153c
if(canqlock(cmd)){
qunlock(cmd);
error(Egreg);
}
if(cmd->pid != u->p->pid)
error(Egreg);
if (n > DATASIZE)
.
150c
cmd->pid = 0;
qunlock(cmd);
.
148c
*a++ = 0; *a++ = 0;
.
146c
}
if(cmd->pid != u->p->pid)
error(Egreg);
.
143c
if(canqlock(cmd)){
.
134a
/*void scsidump(void); scsidump();*/
.
123c
{
Scsi *cmd = &staticcmd;
if((c->qid.path & CHDIR) || c->qid.path==1)
return;
if((c->qid.path & 0xf) == Qcmd){
if(canqlock(cmd) || cmd->pid == u->p->pid){
cmd->pid = 0;
qunlock(cmd);
}
}
}
.
27c
#define DATASIZE (8*1024)
static uchar datablk[DATASIZE]; /* BUG */
.
## diffname port/devscsi.c 1991/0427
## diff -e /n/bootesdump/1991/0423/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0427/sys/src/9/gnot/devscsi.c
98,103d
## diffname port/devscsi.c 1991/0514
## diff -e /n/bootesdump/1991/0427/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0514/sys/src/9/gnot/devscsi.c
33a
void *
dmaalloc(ulong n)
{
return ialloc(n, 0);
}
.
## diffname port/devscsi.c 1991/0627
## diff -e /n/bootesdump/1991/0514/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0627/sys/src/9/gnot/devscsi.c
581a
kprint("resetting...");
PUT(Own_id, ownid);
PUT(Cmd, Reset);
break;
.
107c
devstat(c, db, 0, 0, scsigeno);
.
## diffname port/devscsi.c 1991/0705
## diff -e /n/bootesdump/1991/0627/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0705/sys/src/9/gnot/devscsi.c
582,585d
107c
devstat(c, db, 0, 0, scsigen);
.
## diffname port/devscsi.c 1991/0706
## diff -e /n/bootesdump/1991/0705/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0706/sys/src/9/gnot/devscsi.c
581a
kprint("resetting...");
PUT(Own_id, ownid);
PUT(Cmd, Reset);
break;
.
107c
devstat(c, db, 0, 0, scsigeno);
.
## diffname port/devscsi.c 1991/0927
## diff -e /n/bootesdump/1991/0706/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/0927/sys/src/9/gnot/devscsi.c
453,469d
396a
void
scsireset(void)
{
static int alloced = 0;
int i;
addportintr(scsiintr);
if(!alloced){
for(i = 0; i < Nbuf; i++)
scsifree(scsialloc(DATASIZE));
alloced = 1;
}
}
void
scsiinit(void)
{
isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L);
if (isscsi >= 0) {
DEV->stat = Scsirst;
WAIT; nop(); WAIT;
DEV->stat = Inten;
while (DEV->stat & (INTRQ|DMA))
nop();
ownid &= 0x0f; /* possibly advanced features */
ownid |= 0x80; /* 16MHz */
PUT(Own_id, ownid);
PUT(Cmd, Reset);
}
}
.
387a
static int isscsi;
.
343a
int
scsibread(int dev, Scsibuf *b, long n, long blocksize, long blockno)
{
Scsi *cmd;
cmd = scsicmd(dev, ScsiRead, b, n*blocksize);
if(waserror()){
qunlock(cmd);
nexterror();
}
cmd->cmdblk[1] = blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
scsiexec(cmd, ScsiIn);
n = cmd->data.ptr - cmd->data.base;
poperror();
qunlock(cmd);
return n;
}
int
scsibwrite(int dev, Scsibuf *b, long n, long blocksize, long blockno)
{
Scsi *cmd;
cmd = scsicmd(dev, ScsiWrite, b, n*blocksize);
if(waserror()){
qunlock(cmd);
nexterror();
}
cmd->cmdblk[1] = blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
scsiexec(cmd, ScsiOut);
n = cmd->data.ptr - cmd->data.base;
poperror();
qunlock(cmd);
return n;
}
/*
* allocate a scsi buf of any length
* must be called at ialloc time and never freed
*/
Scsibuf *
scsialloc(ulong n)
{
Scsibuf *b;
uchar *x;
long m;
b = ialloc(sizeof *b, 0);
b->virt = b->phys = ialloc(n, 0);
return b;
}
/*
* get a scsi io buffer of DATASIZE size
*/
Scsibuf *
scsibuf(void)
{
Scsibuf *b;
for(;;) {
lock(&scsibufalloc);
if(b = scsibufalloc.free) {
scsibufalloc.free = b->next;
unlock(&scsibufalloc);
return b;
}
unlock(&scsibufalloc);
resrcwait("no scsi buffers");
}
}
void
scsifree(Scsibuf *b)
{
lock(&scsibufalloc);
b->next = scsibufalloc.free;
scsibufalloc.free = b;
unlock(&scsibufalloc);
}
.
339c
if((status&0xff00) != 0x6000)
.
337a
poperror();
scsifree(cmd->b);
.
336c
cmd = scsicmd(dev, ScsiGetcap, scsibuf(), 8);
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiIn);
.
333c
Scsi *cmd;
.
325c
if((status&0xff00) != 0x6000)
.
323a
poperror();
scsifree(cmd->b);
.
322c
cmd = scsicmd(dev, ScsiExtsens, scsibuf(), 18);
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiIn);
.
319c
Scsi *cmd;
.
311c
if((status&0xff00) != 0x6000)
.
309c
cmd = scsicmd(dev, ScsiTestunit, scsibuf(), 0);
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiOut);
poperror();
scsifree(cmd->b);
.
306c
Scsi *cmd;
.
296c
cmd->b = b;
cmd->data.base = b->virt;
.
293c
case ScsiGetcap:
.
290c
case ScsiExtsens:
.
288c
case ScsiTestunit:
.
285c
cmd->cmd.lim = &cmd->cmdblk[12];
break;
.
283c
cmd->cmd.lim = &cmd->cmdblk[10];
break;
.
281c
cmd->cmd.lim = &cmd->cmdblk[6];
break;
.
279c
switch(cmdbyte >> 5){
.
273,274c
cmd->target = dev >> 3;
cmd->lun = dev & 7;
.
270,271d
266c
scsicmd(int dev, int cmdbyte, Scsibuf *b, long size)
.
244c
}else
.
241c
if(offset == 0){
.
238a
poperror();
scsifree(cmd->b);
.
237c
scsiexec(cmd, ScsiOut);
.
232c
cmd->b = scsibuf();
cmd->data.base = cmd->b->virt;
if(waserror()){
scsifree(cmd->b);
nexterror();
}
.
211c
if(n < 6 || n > sizeof cmd->cmdblk)
.
209c
}else switch(c->qid.path & 0xf){
.
201a
.
189c
}else
.
186c
if(offset == 0){
.
183a
poperror();
scsifree(cmd->b);
.
181c
scsiexec(cmd, ScsiIn);
.
177c
cmd->b = scsibuf();
cmd->data.base = cmd->b->virt;
if(waserror()){
scsifree(cmd->b);
nexterror();
}
.
163,164c
*a++ = 0;
*a++ = 0;
*a++ = cmd->status >> 8;
*a = cmd->status;
.
154c
if(n < 4)
.
152c
}else switch(c->qid.path & 0xf){
.
141c
if(n == 0)
.
80,85d
34,38c
int scsiexec(Scsi*, int);
int scsiintr(void);
.
31d
26,29d
23d
17a
struct Scsidata
{
uchar *base;
uchar *lim;
uchar *ptr;
};
struct Scsi
{
QLock;
ulong pid;
ushort target;
ushort lun;
ushort rflag;
ushort status;
Scsidata cmd;
Scsidata data;
Scsibuf *b;
uchar *save;
uchar cmdblk[16];
};
struct{
Lock;
Scsibuf *free;
}scsibufalloc;
static Scsi staticcmd; /* BUG: should be one per scsi device */
enum
{
Qdir,
Qcmd,
Qdata,
Qdebug,
};
.
14,15c
typedef struct Scsi Scsi;
typedef struct Scsidata Scsidata;
#define Nbuf 4
#define DATASIZE (8*1024)
enum
{
ScsiTestunit = 0x00,
ScsiExtsens = 0x03,
ScsiGetcap = 0x25,
ScsiRead = 0x08,
ScsiWrite = 0x0a,
/*
* data direction
*/
ScsiIn = 1,
ScsiOut = 0,
.
10,11d
## diffname port/devscsi.c 1991/1112
## diff -e /n/bootesdump/1991/0927/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/1112/sys/src/9/gnot/devscsi.c
95c
devdir(c, (Qid){qid,0}, tab->name, tab->length, eve, tab->perm, dp);
.
92c
devdir(c, (Qid){qid,0}, name, 0, eve, 0555, dp);
.
88c
devdir(c, (Qid){qid,0}, "id", 1, eve, 0666, dp);
.
86c
devdir(c, (Qid){qid,0}, ".", 0, eve, 0555, dp);
.
70,72c
"cmd", {Qcmd}, 0, 0666,
"data", {Qdata}, 0, 0666,
"debug", {Qdebug}, 1, 0666,
.
## diffname port/devscsi.c 1991/1220
## diff -e /n/bootesdump/1991/1112/sys/src/9/gnot/devscsi.c /n/bootesdump/1991/1220/sys/src/9/gnot/devscsi.c
80a
void scsireset(void);
.
## diffname port/devscsi.c 1992/0111
## diff -e /n/bootesdump/1991/1220/sys/src/9/gnot/devscsi.c /n/bootesdump/1992/0111/sys/src/9/gnot/devscsi.c
6c
#include "../port/error.h"
.
## diffname port/devscsi.c 1992/0321
## diff -e /n/bootesdump/1992/0111/sys/src/9/gnot/devscsi.c /n/bootesdump/1992/0321/sys/src/9/gnot/devscsi.c
2c
#include "../port/lib.h"
.
## diffname port/devscsi.c 1992/0625
## diff -e /n/bootesdump/1992/0321/sys/src/9/gnot/devscsi.c /n/bootesdump/1992/0625/sys/src/9/gnot/devscsi.c
574,578d
570,572d
507,510c
free(b);
.
491,501c
b = smalloc(sizeof(Scsibuf)+DATASIZE);
b->phys = (void*)(b + 1);
b->virt = b->phys;
return b;
.
468,483d
54,58d
## diffname port/devscsi.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/gnot/devscsi.c /n/bootesdump/1992/0711/sys/src/9/gnot/devscsi.c
561a
USED(arg);
.
311a
USED(c, dp);
.
305a
USED(c);
.
150a
USED(c, name, omode, perm);
.
104a
USED(tab, ntab);
.
98a
USED(tab, ntab, s);
.
## diffname port/devscsi.c 1992/0808
## diff -e /n/bootesdump/1992/0808/sys/src/9/gnot/devscsi.c /n/bootesdump/1992/0808/sys/src/9/port/devscsi.c
619,737c
lock(&scsibufalloc);
b->next = scsibufalloc.free;
scsibufalloc.free = b;
unlock(&scsibufalloc);
.
617c
scsifree(Scsibuf *b)
.
564,615d
561a
return 0; /* not reached */
.
481,560c
unlock(&scsibufalloc);
resrcwait("no scsi buffers");
.
475,479c
for(;;) {
lock(&scsibufalloc);
if(b = scsibufalloc.free) {
scsibufalloc.free = b->next;
unlock(&scsibufalloc);
return b;
}
.
425a
scsiwp(int dev)
{
Scsi *cmd;
int r, status;
cmd = scsicmd(dev, ScsiModesense, scsibuf(), 12);
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiIn);
r = cmd->data.base[2] & 0x80;
poperror();
scsifree(cmd->b);
qunlock(cmd);
if ((status&0xffff) != 0x6000)
error(Eio);
return r;
}
int
.
421a
if(status & 0xFF)
scsisense(dev, p);
.
345a
case ScsiModesense:
cmd->cmdblk[2] = 1;
/* fall through */
.
295c
scsidebugs[(c->qid.path>>4)&7] = (*a=='1');
.
251c
scsiownid=*a;
.
233c
*a="01"[scsidebugs[(c->qid.path>>4)&7]!=0];
.
184c
*a = scsiownid;
.
119a
void
scsireset(void)
{
int i;
for(i = 0; i < Nbuf; i++)
scsifree(scsialloc(DATASIZE));
lock(&scsibufalloc);
unlock(&scsibufalloc);
resetscsi();
}
void
scsiinit(void)
{
initscsi();
}
.
74,77d
71,72c
extern int scsidebugs[];
extern int scsiownid;
.
25,53d
15,23c
struct{
Lock;
Scsibuf *free;
}scsibufalloc;
.
12,13c
#define Nbuf 2
#define DATASIZE (32*512)
.
8d
## diffname port/devscsi.c 1992/0825
## diff -e /n/bootesdump/1992/0808/sys/src/9/port/devscsi.c /n/bootesdump/1992/0825/sys/src/9/port/devscsi.c
428a
}
int
scsimodesense(int dev, int page, void *p, int size)
{
Scsi *cmd;
int status;
cmd = scsicmd(dev, ScsiModesense, scsibuf(), size);
cmd->cmdblk[2] = page;
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiIn);
memmove(p, cmd->data.base, size);
poperror();
scsifree(cmd->b);
qunlock(cmd);
if ((status&0xffff) != 0x6000)
error(Eio);
return status&0xff;
.
409a
scsiinquiry(int dev, void *p, int size)
{
Scsi *cmd;
int status;
cmd = scsicmd(dev, ScsiInquiry, scsibuf(), size);
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiIn);
memmove(p, cmd->data.base, size);
poperror();
scsifree(cmd->b);
qunlock(cmd);
if((status&0xff00) != 0x6000)
error(Eio);
if(status & 0xFF)
scsisense(dev, p);
return status&0xff;
}
int
.
328a
case ScsiInquiry:
.
## diffname port/devscsi.c 1992/0829
## diff -e /n/bootesdump/1992/0825/sys/src/9/port/devscsi.c /n/bootesdump/1992/0829/sys/src/9/port/devscsi.c
12a
#undef DATASIZE
#define DATASIZE (64*1024)
.
## diffname port/devscsi.c 1992/0921
## diff -e /n/bootesdump/1992/0829/sys/src/9/port/devscsi.c /n/bootesdump/1992/0921/sys/src/9/port/devscsi.c
540c
resrcwait(0);
.
538d
533c
b = scsibufalloc.free;
if(b != 0) {
.
## diffname port/devscsi.c 1992/1009
## diff -e /n/bootesdump/1992/0921/sys/src/9/port/devscsi.c /n/bootesdump/1992/1009/sys/src/9/port/devscsi.c
351a
if(waserror()){
scsifree(cmd->b);
qunlock(cmd);
nexterror();
}
status = scsiexec(cmd, ScsiOut);
poperror();
scsifree(cmd->b);
qunlock(cmd);
if((status&0xff00) != 0x6000)
error(Eio);
return status&0xff;
}
int
scsistartstop(int dev, int cmdbyte)
{
Scsi *cmd;
int status;
cmd = scsicmd(dev, cmdbyte, scsibuf(), 0);
.
326a
case ScsiStartunit:
cmd->cmdblk[4] = 1;
break;
.
## diffname port/devscsi.c 1992/1029
## diff -e /n/bootesdump/1992/1009/sys/src/9/port/devscsi.c /n/bootesdump/1992/1029/sys/src/9/port/devscsi.c
545,575d
86,91c
scsibufreset(DATASIZE);
.
16,19d
11d
## diffname port/devscsi.c 1992/1209
## diff -e /n/bootesdump/1992/1029/sys/src/9/port/devscsi.c /n/bootesdump/1992/1209/sys/src/9/port/devscsi.c
469a
*/
USED(dev);
return 0;
.
452a
/* Device specific
.
15d
12,13d
## diffname port/devscsi.c 1992/1221
## diff -e /n/bootesdump/1992/1209/sys/src/9/port/devscsi.c /n/bootesdump/1992/1221/sys/src/9/port/devscsi.c
11c
#define DATASIZE (64*512)
.
## diffname port/devscsi.c 1993/0407
## diff -e /n/bootesdump/1992/1221/sys/src/9/port/devscsi.c /n/bootesdump/1993/0407/sys/src/9/port/devscsi.c
527,530c
switch(cmdbyte){
case ScsiWrite:
cmd->cmdblk[1] |= blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
break;
default:
cmd->cmdblk[2] = blockno >> 24;
cmd->cmdblk[3] = blockno >> 16;
cmd->cmdblk[4] = blockno >> 8;
cmd->cmdblk[5] = blockno;
cmd->cmdblk[7] = n>>8;
cmd->cmdblk[8] = n;
break;
}
.
522c
int cmdbyte;
if(blockno <= 0x1fffff && n <= 256)
cmdbyte = ScsiWrite;
else
cmdbyte = ScsiExtwrite;
cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
.
506,509c
switch(cmdbyte){
case ScsiRead:
cmd->cmdblk[1] |= blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
break;
default:
cmd->cmdblk[2] = blockno >> 24;
cmd->cmdblk[3] = blockno >> 16;
cmd->cmdblk[4] = blockno >> 8;
cmd->cmdblk[5] = blockno;
cmd->cmdblk[7] = n>>8;
cmd->cmdblk[8] = n;
break;
}
.
501c
if(blockno <= 0x1fffff && n <= 256)
cmdbyte = ScsiRead;
else
cmdbyte = ScsiExtread;
cmd = scsicmd(dev, cmdbyte, b, n*blocksize);
.
499a
int cmdbyte;
.
299a
cmd->cmdblk[1] = cmd->lun << 5;
.
## diffname port/devscsi.c 1993/0501
## diff -e /n/bootesdump/1993/0407/sys/src/9/port/devscsi.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devscsi.c
553,568c
cmd->cmdblk[1] = blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
.
541,548c
cmd = scsicmd(dev, ScsiWrite, b, n*blocksize);
.
513,528c
cmd->cmdblk[1] = blockno >> 16;
cmd->cmdblk[2] = blockno >> 8;
cmd->cmdblk[3] = blockno;
cmd->cmdblk[4] = n;
.
503,508c
cmd = scsicmd(dev, ScsiRead, b, n*blocksize);
.
501d
300d
242c
if(cmd->pid != up->pid)
.
228c
cmd->pid = up->pid;
.
179c
if(cmd->pid != up->pid)
.
164c
if(cmd->pid != up->pid)
.
133c
if(canqlock(cmd) || cmd->pid == up->pid){
.
## diffname port/devscsi.c 1993/1124 # deleted
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devscsi.c /n/fornaxdump/1993/1124/sys/src/brazil/port/devscsi.c
1,536d
|