Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/gnot/scsi.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname gnot/scsi.c 1992/0808
## diff -e /dev/null /n/bootesdump/1992/0808/sys/src/9/gnot/scsi.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"devtab.h"
#include	"io.h"

int	scsiintr(void);

#define	DPRINT	if(debug)kprint

int	scsidebugs[8];
int	scsiownid = 0x08|7; /* enable advanced features */

Scsibuf *
scsialloc(ulong n)
{
	Scsibuf *b;

	b = xalloc(sizeof(Scsibuf));
	b->virt = b->phys = xalloc(n);
	return b;
}

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 int	isscsi;
static QLock	scsilock;
static Rendez	scsirendez;
static uchar *	datap;
static uchar *	datalim;
static long	debug, scsirflag, scsibusy, scsiinservice;

static void
nop(void)
{}

void
resetscsi(void)
{
	static int inited;

	if(!inited)
		addportintr(scsiintr);
	inited = 1;
}

void
initscsi(void)
{
	isscsi = portprobe("scsi", -1, Scsiaddr, -1, 0L);
	if (isscsi >= 0) {
		DEV->stat = Scsirst;
		delay(100);
		DEV->stat = Inten;
		while (DEV->stat & (INTRQ|DMA))
			nop();
		scsiownid &= 0x0f; /* possibly advanced features */
		scsiownid |= 0x80; /* 16MHz */
		PUT(Own_id, scsiownid);
		PUT(Cmd, Reset);
	}
}

static int
scsidone(void *arg)
{
	USED(arg);
	return (scsibusy == 0);
}

int
scsiexec(Scsi *p, int rflag)
{
	long n;

	debug = scsidebugs[p->target&7];
	DPRINT("scsi %d.%d %2.2ux ", p->target, p->lun, *(p->cmd.ptr));
	qlock(&scsilock);
	if(waserror()){
		qunlock(&scsilock);
		DPRINT(" error return\n");
		nexterror();
	}
	scsirflag = rflag;
	p->rflag = rflag;
	datap = p->data.base;
	datalim = p->data.lim;
	if ((scsiownid & 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 (scsiownid & 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);
	/*PUT(Cmd, Select_with_ATN_and_Xfr);*/
	DPRINT("S<");
	sleep(&scsirendez, scsidone, 0);
	DPRINT(">\n");
	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
scsireset0(void)
{
/*	PUT(Control, 0x29);	/* burst DMA, halt on parity error */
	PUT(Control, 0x28);	/* burst DMA, allow parity errors */
	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, phase;
	long n;

	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 */
		n = GET(Tc_hi);
		n = (n<<8)|DEV->data;
		n = (n<<8)|DEV->data;
		datap = datalim - n;
		PUT(Cmd_phase, 0x41);
		PUT(Cmd, Select_and_Xfr);
		break;
	case 0x16:			/* select-and-transfer completed */
	case 0x42:			/* timeout during select */
		scsirun();
		break;
	case 0x4b:			/* unexpected status phase */
		DEV->asr = Target_LUN;
		kprint("lun/status 0x%ux\n", DEV->data);
		phase = DEV->data;
		kprint("phase 0x%ux\n", phase);
		PUT(Tc_hi, 0);
		DEV->data = 0;
		DEV->data = 0;
		switch(phase){
		case 0x50:
		case 0x60:
			break;
		default:
			phase = 0x46;
			break;
		}
		PUT(Cmd_phase, phase);
		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);
		}
		kprint("resetting...");
		PUT(Own_id, scsiownid);
		PUT(Cmd, Reset);
		break;
	}
}
.
## diffname gnot/scsi.c 1993/0501 # deleted
## diff -e /n/bootesdump/1992/0808/sys/src/9/gnot/scsi.c /n/fornaxdump/1993/0501/sys/src/brazil/gnot/scsi.c
1,309d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.