~kris/9p

9hist

bd4a67d71f12e72305d8abdc372f73c30d088dd1 — David du Colombier 34 years ago 2185e6b
Plan 9 from Bell Labs 1992-09-01
3 files changed, 262 insertions(+), 22 deletions(-)

M pc/devfloppy.c
M pc/devhard.c
A port/devcdrom.c
M pc/devfloppy.c => pc/devfloppy.c +14 -12
@@ 12,6 12,8 @@ typedef	struct Drive		Drive;
typedef	struct Controller	Controller;
typedef struct Type		Type;

#define DPRINT if(0)print

/* bits in the registers */
enum
{


@@ 552,7 554,7 @@ floppycmd(void)
	for(i = 0; i < fl.ncmd; i++){
		for(tries = 0; ; tries++){
			if(tries > 1000){
print("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
			DPRINT("cmd %ux can't be sent (%d %ux)\n", fl.cmd[0], i, inb(Pmsr));
				fl.confused = 1;
				return -1;
			}


@@ 635,7 637,7 @@ floppysense(void)
	if(floppycmd() < 0)
		return -1;
	if(floppyresult() < 2){
/*print("can't read sense response\n");/**/
		DPRINT("can't read sense response\n");
		fl.confused = 1;
		return -1;
	}


@@ 682,7 684,7 @@ floppyrecal(Drive *dp)
	}
	dp->cyl = fl.stat[1]/dp->t->steps;
	if(dp->cyl != 0){
		print("recalibrate went to wrong cylinder %d\n", dp->cyl);
		DPRINT("recalibrate went to wrong cylinder %d\n", dp->cyl);
		dp->confused = 1;
		return -1;
	}


@@ 732,13 734,13 @@ floppyseek(Drive *dp, long off)
	if(dp->cyl == dp->tcyl)
		return dp->cyl;

/* print("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead); /**/
	DPRINT("seeking tcyl %d, thead %d\n", dp->tcyl, dp->thead);
	fl.ncmd = 0;
	fl.cmd[fl.ncmd++] = Fseek;
	fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev;
	fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;
	if(floppycmd() < 0){
		print("seek cmd failed\n");
		DPRINT("seek cmd failed\n");
		return -1;
	}
	floppywait();


@@ 747,7 749,7 @@ floppyseek(Drive *dp, long off)
		return -1;
	}
	if((fl.stat[0] & (Codemask|Seekend)) != Seekend){
		print("seek failed\n");
		DPRINT("seek failed\n");
		dp->confused = 1;
		return -1;
	}


@@ 794,8 796,8 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
	if(floppyseek(dp, off) < 0)
		error(Eio);

/*print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);/**/
	DPRINT("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
	dp->tcyl, dp->thead, dp->tsec, a, dp->len);

	/*
	 *  set up the dma (dp->len may be trimmed)


@@ 818,7 820,7 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
	fl.cmd[fl.ncmd++] = 0xFF;
	if(floppycmd() < 0){
		spllo();
/*		print("xfer cmd failed\n");/**/
		DPRINT("xfer cmd failed\n");
		error(Eio);
	}



@@ 832,14 834,14 @@ floppyxfer(Drive *dp, int cmd, void *a, long off, long n)
	 *  check for errors
	 */
	if(fl.nstat < 7){
/*		print("xfer result failed %lux\n", inb(Pmsr));/**/
		DPRINT("xfer result failed %lux\n", inb(Pmsr));
		fl.confused = 1;
		error(Eio);
	}
	if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){
		print("xfer failed %lux %lux %lux\n", fl.stat[0],
		DPRINT("xfer failed %lux %lux %lux\n", fl.stat[0],
			fl.stat[1], fl.stat[2]);
		print("offset %lud len %d\n", off, dp->len);
		DPRINT("offset %lud len %d\n", off, dp->len);
		dp->confused = 1;
		error(Eio);
	}

M pc/devhard.c => pc/devhard.c +12 -10
@@ 6,6 6,8 @@
#include	"io.h"
#include	"../port/error.h"

#define DPRINT if(0)print

typedef	struct Drive		Drive;
typedef	struct Ident		Ident;
typedef	struct Controller	Controller;


@@ 459,7 461,7 @@ cmdreadywait(Controller *cp)
	start = m->ticks;
	while((inb(cp->pbase+Pstatus) & (Sready|Sbusy)) != Sready)
		if(TK2MS(m->ticks - start) > 1){
print("cmdreadywait failed\n");
			DPRINT("cmdreadywait failed\n");
			error(Eio);
		}
}


@@ 473,7 475,7 @@ hardrepl(Drive *dp, long bblk)
		return;
	for(i = 0; i < dp->repl.nrepl; i++){
		if(dp->repl.blk[i] == bblk)
			print("found bblk %ld at offset %ld\n", bblk, i);
			DPRINT("found bblk %ld at offset %ld\n", bblk, i);
	}
}



@@ 559,10 561,10 @@ hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
	sleep(&cp->r, cmddone, cp);

	if(cp->status & Serr){
		print("hd%d err: lblk %ld status %lux, err %lux\n",
		DPRINT("hd%d err: lblk %ld status %lux, err %lux\n",
			dp-hard, lblk, cp->status, cp->error);
		print("\tcyl %d, sec %d, head %d\n", cyl, sec, head);
		print("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
		DPRINT("\tcyl %d, sec %d, head %d\n", cyl, sec, head);
		DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar);
		hardrepl(dp, lblk+cp->sofar);
		error(Eio);
	}


@@ 597,7 599,7 @@ hardsetbuf(Drive *dp)
	sleep(&cp->r, cmddone, cp);

	if(cp->status & Serr)
		print("hd%d setbuf err: status %lux, err %lux\n",
		DPRINT("hd%d setbuf err: status %lux, err %lux\n",
			dp-hard, cp->status, cp->error);

	poperror();


@@ 632,7 634,7 @@ hardident(Drive *dp)
	outb(cp->pbase+Pcmd, Cident);
	sleep(&cp->r, cmddone, cp);
	if(cp->status & Serr){
		print("bad disk ident status\n");
		DPRINT("bad disk ident status\n");
		error(Eio);
	}
	memmove(&dp->id, buf, dp->bytes);


@@ 798,7 800,7 @@ hardintr(Ureg *ur)
	loop = 0;
	while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy){
		if(++loop > 100) {
			print("cmd=%lux status=%lux\n",
			DPRINT("cmd=%lux status=%lux\n",
				cp->cmd, inb(cp->pbase+Pstatus));
			panic("hardintr: wait busy");
		}


@@ 817,7 819,7 @@ hardintr(Ureg *ur)
			loop = 0;
			while(((cp->status = inb(cp->pbase+Pstatus)) & Sdrq) == 0)
				if(++loop > 100) {
					print("cmd=%lux status=%lux\n",
					DPRINT("cmd=%lux status=%lux\n",
						cp->cmd, inb(cp->pbase+Pstatus));
					panic("hardintr: write");
				}


@@ 837,7 839,7 @@ hardintr(Ureg *ur)
		loop = 0;
		while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
			if(++loop > 10000) {
				print("cmd=%lux status=%lux\n",
				DPRINT("cmd=%lux status=%lux\n",
					cp->cmd, inb(cp->pbase+Pstatus));
				panic("hardintr: read/ident");
		}

A port/devcdrom.c => port/devcdrom.c +236 -0
@@ 0,0 1,236 @@
#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"

/*
 * CD-ROM.  Gutted version of devwren.
 */

#define DATASIZE	2048	/* max in a transfer */

typedef struct Drive		Drive;

enum {
	Ndisk=		8,	/* maximum disks */
	/* file types */
	Qdir=		0,
	Qdisk=		1,
};

struct Drive
{
	QLock;
	ulong		blocks;			/* blocks on disk */
	ulong		bsize;			/* bytes per block */
	int		drive;
};

static Drive	cdrom[Ndisk];

static void	cdromsize(int);
static long	cdromio(Chan*, char*, ulong, ulong);

static char	Ecap[] = "CD-ROM device capacity unknown";
static char	EnotCD[] = "not a CD-ROM device";

/*
 *  accepts [0-7].  lun is therefore always zero.
 */
static int
cdromdev(char *p)
{
	int drive;

	if(p == 0 || p[0] == '\0')
		error(Ebadarg);
	if(p[0] < '0' || p[0] > '7' || p[1])
		error(Ebadarg);
	drive = p[0] - '0';
	return (drive << 3) | 0;
}

static int
cdromgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
{
	char name[NAMELEN+4];
	Drive *dp;

	USED(tab, ntab);
	if(s != 0)
		return -1;
	sprint(name, "cd%d", c->dev>>3);
	dp = &cdrom[c->dev>>3];
	devdir(c, (Qid){Qdisk, 0}, name, dp->blocks*dp->bsize, eve, 0444, dirp);
	return 1;
}

void
cdromreset(void)
{
}

void
cdrominit(void)
{
}

/*
 *  param is #R<target>
 */
Chan*
cdromattach(char *param)
{
	Chan *c;
	int drive;

	drive = cdromdev(param);
	cdromsize(drive);
	c = devattach('R', param);
	c->dev = drive;
	return c;
}

Chan*
cdromclone(Chan *c, Chan *nc)
{
	return devclone(c, nc);
}

int
cdromwalk(Chan *c, char *name)
{
	return devwalk(c, name, 0, 0, cdromgen);
}

void
cdromstat(Chan *c, char *dp)
{
	devstat(c, dp, 0, 0, cdromgen);
}

Chan*
cdromopen(Chan *c, int omode)
{
	return devopen(c, omode, 0, 0, cdromgen);
}

void
cdromcreate(Chan *c, char *name, int omode, ulong perm)
{
	USED(c, name, omode, perm);
	error(Eperm);
}

void
cdromclose(Chan *c)
{
	USED(c);
}

void
cdromremove(Chan *c)
{
	USED(c);
	error(Eperm);
}

void
cdromwstat(Chan *c, char *dp)
{
	USED(c, dp);
	error(Eperm);
}

long
cdromread(Chan *c, char *a, long n, ulong offset)
{
	if(c->qid.path == CHDIR)
		return devdirread(c, a, n, 0, 0, cdromgen);
	return cdromio(c, a, n, offset);
}

long
cdromwrite(Chan *c, char *a, long n, ulong offset)
{
	USED(c, a, n, offset);
	error(Eperm);
	return 0;
}

static long
cdromio(Chan *c, char *a, ulong len, ulong offset)
{
	Drive *d;
	Scsibuf *b;
	ulong block, n, max, x;

	d = &cdrom[c->dev>>3];

	block = offset / d->bsize;
	n = (offset + len + d->bsize - 1) / d->bsize - block;
	max = DATASIZE / d->bsize;
	if(n > max)
		n = max;
	if(block + n > d->blocks)
		n = d->blocks - block;
	if(block >= d->blocks || n == 0)
		return 0;
	b = scsibuf();
	if(waserror()){
		scsifree(b);
		nexterror();
	}
	offset %= d->bsize;
	x = scsibread(d->drive, b, n, d->bsize, block);
	if(x < offset)
		len = 0;
	else if(len > x - offset)
		len = x - offset;
	memmove(a, (char*)b->virt + offset, len);
	poperror();
	scsifree(b);
	return len;
}

/*
 *  size disk
 */
static void
cdromsize(int dev)
{
	Drive *dp;
	uchar buf[128];
	long nb, bs;

	dp = &cdrom[dev>>3];
	if(waserror()){
		qunlock(dp);
		nexterror();
	}
	qlock(dp);
	scsiready(dev);
	scsisense(dev, buf);
	/*
	 * capacity not defined on CD-ROM, but most implement it.
	 */
	if(scsicap(dev, buf)!=0)
		error(Ecap);
	nb = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|(buf[3]<<0);
	bs = (buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|(buf[7]<<0);
	if(nb==0 || bs==0)
		error(Ecap);

	scsiinquiry(dev, buf, sizeof buf);
	if(buf[0]!=5 || buf[0]!=4)	/* CD-ROM or CD-R writer */
		print("warning: scsi device %d type=%d, not type 4 or 5\n", dev>>3, buf[0]);
	dp->drive = dev;
	dp->blocks = nb;
	dp->bsize = bs;
	poperror();
	qunlock(dp);
}