~kris/9p

9hist

277a84a906788060bc527f729cc3aaa3dea1800d — David du Colombier 25 years ago e1337a8
Plan 9 from Bell Labs 2000-12-28
1 files changed, 71 insertions(+), 39 deletions(-)

M pc/sdata.c
M pc/sdata.c => pc/sdata.c +71 -39
@@ 97,6 97,7 @@ enum {					/* Command */
	Crd		= 0xC8,		/* Read DMA */
	Cwd		= 0xCA,		/* Write DMA */
	Cwdq		= 0xCC,		/* Write DMA queued */
	Cstandby	= 0xE2,		/* Standby */
	Cid		= 0xEC,		/* Identify Device */
	Csf		= 0xEF,		/* Set Features */
};


@@ 167,12 168,8 @@ enum {					/* offsets into the identify info. */
	Iqdepth		= 75,		/* max. queue depth */
	Imajor		= 80,		/* major version number */
	Iminor		= 81,		/* minor version number */
	Icmdset0	= 82,		/* command sets supported */
	Icmdset1	= 83,		/* command sets supported */
	Icmdset2	= 84,		/* command sets supported extension */
	Icmdset3	= 85,		/* command sets enabled */
	Icmdset4	= 86,		/* command sets enabled */
	Icmdset5	= 87,		/* command sets enabled extension */
	Icsfs		= 82,		/* command set/feature supported */
	Icsfe		= 85,		/* command set/feature enabled */
	Iudma		= 88,		/* ultra DMA mode */
	Ierase		= 89,		/* time for security erase */
	Ieerase		= 90,		/* time for enhanced security erase */


@@ 395,15 392,21 @@ ataready(int cmdport, int ctlport, int dev, int reset, int ready, int micro)
}

static int
atacsfenabled(Drive* drive, vlong csf)
atacsf(Drive* drive, vlong csf, int supported)
{
	ushort *info;
	int cmdset, i, x;

	if(supported)
		info = &drive->info[Icsfs];
	else
		info = &drive->info[Icsfe];
	
	for(i = 0; i < 3; i++){
		x = (csf>>(16*i)) & 0xFFFF;
		if(x == 0)
			continue;
		cmdset = drive->info[Icmdset3+i];
		cmdset = info[i];
		if(cmdset == 0 || cmdset == 0xFFFF)
			return 0;
		return cmdset & x;


@@ 413,21 416,9 @@ atacsfenabled(Drive* drive, vlong csf)
}

static int
atasf(int cmdport, int ctlport, int dev, uchar* command)
atadone(void* arg)
{
	int as, i;

	if(ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 108*1000) < 0)
		return -1;

	for(i = Features; i < Dh; i++)
		outb(cmdport+i, command[i]);
	outb(cmdport+Command, Csf);
	microdelay(100);
	as = ataready(cmdport, ctlport, 0, Bsy, Drdy|Df|Err, 109*1000);
	if(as < 0 || (as & (Df|Err)))
		return -1;
	return 0;
	return ((Ctlr*)arg)->done;
}

static int


@@ 527,7 518,7 @@ ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info)
		for(i = 0; i < 256; i++){
			if(i && (i%16) == 0)
				print("\n");
			print("%4.4uX ", *sp);
			print(" %4.4uX", *sp);
			sp++;
		}
		print("\n");


@@ 797,6 788,39 @@ atasetsense(Drive* drive, int status, int key, int asc, int ascq)
}

static int
atastandby(Drive* drive, int period)
{
	Ctlr* ctlr;
	int cmdport, done;

	ctlr = drive->ctlr;
	drive->command = Cstandby;
	qlock(ctlr);

	cmdport = ctlr->cmdport;
	ilock(ctlr);
	outb(cmdport+Count, period);
	outb(cmdport+Dh, drive->dev);
	ctlr->done = 0;
	ctlr->curdrive = drive;
	ctlr->command = Cstandby;	/* debugging */
	outb(cmdport+Command, Cstandby);
	iunlock(ctlr);

	while(waserror())
		;
	tsleep(ctlr, atadone, ctlr, 30*1000);
	poperror();

	done = ctlr->done;
	qunlock(ctlr);

	if(!done || (drive->status & Err))
		return atasetsense(drive, SDcheck, 4, 8, drive->error);
	return SDok;
}

static int
atamodesense(Drive* drive, uchar* cmd)
{
	int len;


@@ 865,7 889,7 @@ ataabort(Drive* drive, int dolock)
	 */
	if(dolock)
		ilock(drive->ctlr);
	if(atacsfenabled(drive, 0x0000000000004000LL))
	if(atacsf(drive, 0x0000000000004000LL, 0))
		atanop(drive, 0);
	else{
		atasrst(drive->ctlr->ctlport);


@@ 982,12 1006,6 @@ atadmainterrupt(Drive* drive, int count)
	ctlr->done = 1;
}

static int
atapktiodone(void* arg)
{
	return ((Ctlr*)arg)->done;
}

static void
atapktinterrupt(Drive* drive)
{


@@ 1092,9 1110,9 @@ atapktio(Drive* drive, uchar* cmd, int clen)
	while(waserror())
		;
	if(!drive->pktdma)
		sleep(ctlr, atapktiodone, ctlr);
		sleep(ctlr, atadone, ctlr);
	else for(timeo = 0; !ctlr->done; timeo++){
		tsleep(ctlr, atapktiodone, ctlr, 1000);
		tsleep(ctlr, atadone, ctlr, 1000);
		if(ctlr->done)
			break;
		ilock(ctlr);


@@ 1122,12 1140,6 @@ atapktio(Drive* drive, uchar* cmd, int clen)
}

static int
atageniodone(void* arg)
{
	return ((Ctlr*)arg)->done;
}

static int
atageniostart(Drive* drive, int lba)
{
	Ctlr *ctlr;


@@ 1325,7 1337,7 @@ atagenio(Drive* drive, uchar* cmd, int)

		while(waserror())
			;
		tsleep(ctlr, atageniodone, ctlr, 10*1000);
		tsleep(ctlr, atadone, ctlr, 30*1000);
		poperror();
		if(!ctlr->done){
			/*


@@ 1336,6 1348,7 @@ atagenio(Drive* drive, uchar* cmd, int)
			 */
			atadumpstate(drive, cmd, lba, count);
			ataabort(drive, 1);
			qunlock(ctlr);
			return atagenioretry(drive);
		}



@@ 1540,6 1553,10 @@ atainterrupt(Ureg*, void* arg)
	case Cwd:
		atadmainterrupt(drive, drive->count*drive->secsize);
		break;

	case Cstandby:
		ctlr->done = 1;
		break;
	}
	iunlock(ctlr);



@@ 1776,6 1793,7 @@ atarctl(SDunit* unit, char* p, int l)
static int
atawctl(SDunit* unit, Cmdbuf* cb)
{
	int period;
	Ctlr *ctlr;
	Drive *drive;



@@ 1815,6 1833,20 @@ atawctl(SDunit* unit, Cmdbuf* cb)
		else
			error(Ebadctl);
	}
	else if(strcmp(cb->f[0], "standby") == 0){
		switch(cb->nf){
		default:
			error(Ebadctl);
		case 2:
			period = strtol(cb->f[1], 0, 0);
			if(period && (period < 30 || period > 240*5))
				error(Ebadctl);
			period /= 5;
			break;
		}
		if(atastandby(drive, period) != SDok)
			error(Ebadctl);
	}
	else
		error(Ebadctl);
	qunlock(drive);