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

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


## diffname ss/scsi.c 1992/0807
## diff -e /dev/null /n/bootesdump/1992/0807/sys/src/9/ss/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"

static int	ownid = 7;

Scsibuf *
scsialloc(ulong n)
{
	Scsibuf *b;
	KMap *k;
	ulong pa, va;
	int i, j;

	b = xalloc(sizeof(Scsibuf));

	/*
	 * Allocate space in host memory for the io buffer.
	 * Allocate a block and kmap it page by page.  kmap's are initially
	 * in reverse order so rearrange them.
	 * NOTE: dma mustn't cross a 16Mb boundary.
	 */
	i = (n+(BY2PG-1))/BY2PG;
	pa = (ulong)xspanalloc(i*BY2PG, BY2PG, 16*1024*1024) & ~KZERO;
	va = 0;
	k = 0;
	for(j=i-1; j>=0; j--){
		k = kmappa(pa+j*BY2PG, PTEMAINMEM|PTENOCACHE);
		if(va && va != k->va+BY2PG)
			panic("scsialloc va unordered\n");
		va = k->va;
	}
	/*
	 * k->va is the base of the region
	 */
	b->virt = (void*)k->va;
	b->phys = (void*)k->pa;

	return b;
}

/*
 *	NCR 53C90 commands
 */

enum
{
	Dma		= 0x80,
	Nop		= 0x00,
	Flush		= 0x01,
	Reset		= 0x02,
	Busreset	= 0x03,
	Select		= 0x41,
	Transfer	= 0x10,
	Cmdcomplete	= 0x11,
	Msgaccept	= 0x12
};

static QLock	scsilock;	/* access to device */
static Rendez	scsirendez;	/* sleep/wakeup for requesting process */
static Scsi *	curcmd;		/* currently executing command */

struct {
	DMAdev *dma;
	SCSIdev *scsi;
} ioaddr;

void
resetscsi(void)
{
	SCSIdev *dev;
	DMAdev *dma;
	KMap *k;

	k = kmappa(DMA, PTENOCACHE|PTEIO);
	ioaddr.dma = (DMAdev*)k->va;
	k = kmappa(SCSI, PTENOCACHE|PTEIO);
	ioaddr.scsi = (SCSIdev*)k->va;

	dev = ioaddr.scsi;
	dma = ioaddr.dma;

	dev->cmd = Reset;
	dev->cmd = Nop;
	dev->countlo = 0;
	dev->counthi = 0;
	dev->timeout = 146;
	dev->syncperiod = 0;
	dev->syncoffset = 0;
	dev->config = 0x10|(ownid&7);
	dev->cmd = Dma|Nop;

	dma->csr = Dma_Reset;
	delay(1);
	dma->csr = Int_en;
	dma->count = 0;

	putenab(getenab()|ENABDMA); /**/
}

void
initscsi(void)
{
}

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

int
scsiexec(Scsi *p, int rflag)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;
	long n;

	qlock(&scsilock);

	if(waserror()){
		qunlock(&scsilock);
		nexterror();
	}
	p->rflag = rflag;
	p->status = 0;

	dma->csr = Dma_Flush|Int_en;
	dma->addr = (ulong)p->data.ptr;

	dev->counthi = 0;
	dev->countlo = 0;
	dev->cmd = Dma|Nop;
	dev->cmd = Flush;			/* clear scsi fifo */

	while (p->cmd.ptr < p->cmd.lim)
		dev->fifo = *(p->cmd.ptr)++;

	dev->destid = p->target&7;
	n = p->data.lim - p->data.ptr;
	dev->counthi = n>>8;
	dev->countlo = n;
	dev->cmd = Dma|Nop;

	dma->csr = Int_en;

	curcmd = p;
	dev->cmd = Select;

	sleep(&scsirendez, scsidone, 0);
	poperror();
	qunlock(&scsilock);
	return p->status;
}


void
scsibusreset(void)
{
	SCSIdev *dev = ioaddr.scsi;
	int s;

	s = splhi();
	dev->cmd = Nop;
	dev->cmd = Busreset;
	dev->cmd = Nop;
	splx(s);
}

static void
scsimoan(char *msg, int status, int intr, int dmastat)
{
	print("scsiintr: %s:", msg);
	print(" status=%2.2ux step/intr=%3.3ux", status, intr);
	print(" dma=%8.8ux cmd status=%4.4ux\n",
		dmastat, curcmd ? curcmd->status : 0xffff);
}

void
scsiintr(void)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;
	Scsi *p = curcmd;
	int status, step, intr, n;
	ulong m, csr;

	csr = dma->csr;

	status = dev->status;
	step = dev->step;
	intr = dev->intr;

	intr |= ((step&7)<<8);

	if(p == 0 || (intr & 0x80)) {	/* SCSI bus reset */
		dev->cmd = Nop;
		goto Done;
	}

	switch(p->status>>8){
	case 0x00:		/* Select was issued */
		switch(intr){
		default:
			scsimoan("bad case", status, intr, csr);
			print("cmd = #%2.2ux\n", dev->cmd);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x020:	/* arbitration complete, selection timed out */
			goto Done;
		case 0x218:	/* selection complete, no command phase */
			p->status = 0x1000;
			scsimoan("no cmd phase", status, intr, csr);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x318:	/* command phase ended prematurely */
			n = (p->cmd.lim - p->cmd.base) - (dev->fflags & 0x1f);
			p->status = (0x30+n)<<8;
			scsimoan("short cmd phase", status, intr, csr);
			resetscsi();
			scsibusreset();
			goto Done;
		case 0x418:	/* select sequence complete */
			p->status = 0x4100;
			if((status & 0x07) == p->rflag){
				dma->csr = p->rflag ? En_dma|Write|Int_en : En_dma|Int_en;
				dev->cmd = Dma|Transfer;
				return;
			}else if((status & 0x07) != 3){
				scsimoan("weird phase after cmd",
					status, intr, csr);
				goto Done;
			}
			/* else fall through */
		}

	case 0x41:	/* data transfer, if any, is finished */
		p->status = 0x4600;
		p->data.ptr = p->data.lim - ((dev->counthi<<8)|dev->countlo);
		if((status & 0x07) != 3){
			scsimoan("weird phase after xfr",
				status, intr, csr);
			goto Done;
		}

		if(p->rflag)
			while(dma->csr & Pack_cnt)
				;

		dev->cmd = Cmdcomplete;
		return;

	case 0x46:	/* Cmdcomplete was issued */
		p->status = 0x6000|dev->fifo;
		m = dev->fifo;
		dev->cmd = Msgaccept;
		return;

	case 0x60:	/* Msgaccept was issued */
		goto Done;
	}
Done:
	curcmd = 0;
	wakeup(&scsirendez);
}

#ifdef notdef
void
scsidump(void)
{
	SCSIdev *dev = ioaddr.scsi;
	DMAdev *dma = ioaddr.dma;

	print("\nscsi:\n");
	print("	countlo=0x%2.2ux\n", dev->countlo);
	print("	counthi=0x%2.2ux\n", dev->counthi);
	print("	cmd    =0x%2.2ux\n", dev->cmd);
	print("	status =0x%2.2ux\n", dev->status);
	print("	intr   =0x%2.2ux\n", dev->intr);
	print("	step   =0x%2.2ux\n", dev->step);
	print("	fflags =0x%2.2ux\n", dev->countlo);
	print("	config =0x%2.2ux\n", dev->config);
	print("dma:\n");
	print("	csr    =0x%8.8ux\n", dma->csr);
	print("	addr   =0x%8.8ux\n", dma->addr);
	print("	count  =0x%4.4ux\n", dma->count);
	print("	diag   =0x%8.8ux\n", dma->diag);
}
#endif
.
## diffname ss/scsi.c 1992/0808
## diff -e /n/bootesdump/1992/0807/sys/src/9/ss/scsi.c /n/bootesdump/1992/0808/sys/src/9/ss/scsi.c
263a
		USED(m);
.
257a
			case 8:
				dma->csr = Drain|Int_en;
				/*FALLTHROUGH*/

			case 9:
				while(dma->csr & Pack_cnt)
					;
				break;

			default:
				break;
			}
		}


.
254,256c
		if(p->rflag){
			switch(dmatype){
.
102a
	dmatype = (dma->csr>>28) & 0xF;

.
95c
	dev->config = 0x10|(scsiownid&7);
.
11a
static int	dmatype;

.
10c
int	scsiownid = 7;
int	scsidebugs[8];
.
## diffname ss/scsi.c 1992/0811
## diff -e /n/bootesdump/1992/0808/sys/src/9/ss/scsi.c /n/bootesdump/1992/0811/sys/src/9/ss/scsi.c
108a
print("scsi config #%2.2ux\n", dev->config);
.
10c
uchar	scsiownid = 7;
.
## diffname ss/scsi.c 1992/0812
## diff -e /n/bootesdump/1992/0811/sys/src/9/ss/scsi.c /n/bootesdump/1992/0812/sys/src/9/ss/scsi.c
109d
92c
	dev->cmd = Dma|Nop;			/* 2 are necessary */
	dev->cmd = Dma|Nop;

.
## diffname ss/scsi.c 1992/0813
## diff -e /n/bootesdump/1992/0812/sys/src/9/ss/scsi.c /n/bootesdump/1992/0813/sys/src/9/ss/scsi.c
311c
	print("	fflags =0x%2.2ux\n", dev->fflags);
.
306c
	print("	countmi=0x%2.2ux\n", dev->countmi);
.
254c
		p->data.ptr = p->data.lim - ((dev->countmi<<8)|dev->countlo);
.
169,182d
155a
	dev->countmi = n>>8;
.
154d
145a
	dev->countmi = 0;
.
144d
109a
	/*
	 * try to determine chip type
	dev->conf2 = 0;
	dev->conf2 = 0x0A;
	delay(1);
	if((dev->conf2 & 0x0F) == 0x0A){
		dev->conf3 = 0;
		dev->conf3 = 0x05;
		delay(1);
		if(dev->conf3 == 0x05)
			print("scsi type ESP236\n");
		else
			print("scsi type ESP100A\n");
	}
	else
		print("scsi type NCR53C90\n");
	 */

	dev->cmd = Reset;
	dev->cmd = Dma|Nop;			/* 2 are necessary for some chips */
	dev->cmd = Dma|Nop;

	dev->clkconf = 4;			/* BUG: 20MHz */
	dev->timeout = 160;			/* BUG: magic */
	dev->syncperiod = 0;
	dev->syncoffset = 0;
	dev->config = Penable|(scsiownid&7);

	intr = dev->intr;
	USED(intr);

.
91,102d
81a
	uchar intr;
.
75a
static void
scsibusreset(void)
{
	SCSIdev *dev = ioaddr.scsi;
	int s;
	uchar intr;

	s = splhi();
	dev->config |= ResetIntDis;
	dev->cmd = Busreset;
	dev->config &= ~ResetIntDis;
	intr = dev->intr;
	USED(intr);
	splx(s);
}

.
54,56c
	Dma		= 0x80,		/* NCR 53C90 commands */
.
50,52c
enum {
	ResetIntDis	= 0x40,		/* config regsiter */
	Penable		= 0x10,
.
## diffname ss/scsi.c 1992/0820
## diff -e /n/bootesdump/1992/0813/sys/src/9/ss/scsi.c /n/bootesdump/1992/0820/sys/src/9/ss/scsi.c
297d
51c
	ResetIntDis	= 0x40,		/* config register */
.
## diffname ss/scsi.c 1992/0908
## diff -e /n/bootesdump/1992/0820/sys/src/9/ss/scsi.c /n/bootesdump/1992/0908/sys/src/9/ss/scsi.c
33,45c
	va = kmapregion(pa, i*BY2PG, PTEMAINMEM|PTENOCACHE);

	b->virt = (void*)va;
	b->phys = (void*)pa;
.
27,28d
21c
	int i;
.
## diffname ss/scsi.c 1992/0912
## diff -e /n/bootesdump/1992/0908/sys/src/9/ss/scsi.c /n/bootesdump/1992/0912/sys/src/9/ss/scsi.c
19d
## diffname ss/scsi.c 1993/0501 # deleted
## diff -e /n/bootesdump/1992/0912/sys/src/9/ss/scsi.c /n/fornaxdump/1993/0501/sys/src/brazil/ss/scsi.c
1,326d

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.