Exemple #1
0
int
sdmodesense(SDreq *r, uchar *cmd, void *info, int ilen)
{
	int len;
	uchar *data;

	/*
	 * Fake a vendor-specific request with page code 0,
	 * return the drive info.
	 */
	if((cmd[2] & 0x3F) != 0 && (cmd[2] & 0x3F) != 0x3F)
		return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
	len = (cmd[7]<<8)|cmd[8];
	if(len == 0)
		return SDok;
	if(len < 8+ilen)
		return sdsetsense(r, SDcheck, 0x05, 0x1A, 0);
	if(r->data == nil || r->dlen < len)
		return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
	data = r->data;
	memset(data, 0, 8);
	data[0] = ilen>>8;
	data[1] = ilen;
	if(ilen)
		memmove(data+8, info, ilen);
	r->rlen = 8+ilen;
	return sdsetsense(r, SDok, 0, 0, 0);
}
Exemple #2
0
static int
aoerio(SDreq *r)
{
    int i, count, rw;
    uvlong lba;
    Ctlr *c;
    SDunit *u;

    u = r->unit;
    c = u->dev->ctlr;
//	if(c->feat & Datapi)
//		return aoeriopkt(r, d);

    if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91) {
        qlock(c);
        i = flushcache(c);
        qunlock(c);
        if(i == 0)
            return sdsetsense(r, SDok, 0, 0, 0);
        return sdsetsense(r, SDcheck, 3, 0xc, 2);
    }

    if((i = sdfakescsi(r)) != SDnostatus) {
        r->status = i;
        return i;
    }
    if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
        return i;
    r->rlen = aoebio(u, r->lun, rw == SDwrite, r->data, count, lba);
    return r->status = SDok;
}
Exemple #3
0
int
sdfakescsirw(SDreq *r, uvlong *llba, int *nsec, int *rwp)
{
	uchar *c;
	int rw, count;
	uvlong lba;

	c = r->cmd;
	rw = SDread;
	if((c[0] & 0xf) == 0xa)
		rw = SDwrite;
	switch(c[0]){
	case 0x08:	/* read6 */
	case 0x0a:
		lba = (c[1] & 0xf)<<16 | c[2]<<8 | c[3];
		count = c[4];
		break;
	case 0x28:	/* read10 */
	case 0x2a:
		lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
		count = c[7]<<8 | c[8];
		break;
	case 0xa8:	/* read12 */
	case 0xaa:
		lba = c[2]<<24 | c[3]<<16 | c[4]<<8 | c[5];
		count = c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
		break;
	case 0x88:	/* read16 */
	case 0x8a:
		/* ata commands only go to 48-bit lba */
		if(c[2] || c[3])
			return sdsetsense(r, SDcheck, 3, 0xc, 2);
		lba = (uvlong)c[4]<<40 | (uvlong)c[5]<<32;
		lba |= c[6]<<24 | c[7]<<16 | c[8]<<8 | c[9];
		count = c[10]<<24 | c[11]<<16 | c[12]<<8 | c[13];
		break;
	default:
		print("%s: bad cmd 0x%.2ux\n", r->unit->name, c[0]);
		r->status  = sdsetsense(r, SDcheck, 0x05, 0x20, 0);
		return SDcheck;
	}
	if(r->data == nil)
		return SDok;
	if(r->dlen < count * r->unit->secsize)
		count = r->dlen/r->unit->secsize;
	if(rwp)
		*rwp = rw;
	*llba = lba;
	*nsec = count;
	return SDnostatus;
}
Exemple #4
0
static int
viorio(SDreq *r)
{
	int i, count, rw;
	uvlong lba;
	SDunit *u;

	u = r->unit;
	if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
		if(vioreq(u->dev->ctlr, 4, nil, 0, 0, 0) != 0)
			return sdsetsense(r, SDcheck, 3, 0xc, 2);
		return sdsetsense(r, SDok, 0, 0, 0);
	}
	if((i = sdfakescsi(r)) != SDnostatus)
		return r->status = i;
	if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
		return i;
	r->rlen = viobio(u, r->lun, rw == SDwrite, r->data, count, lba);
	return r->status = SDok;
}
Exemple #5
0
static int
looprio(SDreq *r)
{
	int i, count, rw;
	uvlong lba;
	SDunit *u;

	u = r->unit;

	if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91)
		return sdsetsense(r, SDok, 0, 0, 0);

	if((i = sdfakescsi(r)) != SDnostatus)
		return r->status = i;
	if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
		return i;
	r->rlen = loopbio(u, r->lun, rw == SDwrite, r->data, count, lba);
	return r->status = SDok;
}
Exemple #6
0
static int
aoerio(SDreq *r)
{
	int i, count;
	uvlong lba;
	char *name;
	uchar *cmd;
	long (*rio)(Chan*, void*, long, vlong);
	Ctlr *c;
	SDunit *unit;

	unit = r->unit;
	c = unit->dev->ctlr;
//	if(c->feat & Datapi)
//		return aoeriopkt(r, d);

	cmd = r->cmd;
	name = unit->name;

	if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
//		qlock(c);
//		i = flushcache();
//		qunlock(c);
//		if(i == 0)
//			return sdsetsense(r, SDok, 0, 0, 0);
		return sdsetsense(r, SDcheck, 3, 0xc, 2);
	}

	if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){
		r->status = i;
		return i;
	}

	switch(*cmd){
	case 0x88:
	case 0x28:
		rio = devtab[c->c->type]->read;
		break;
	case 0x8a:
	case 0x2a:
		rio = devtab[c->c->type]->write;
		break;
	default:
		print("%s: bad cmd %#.2ux\n", name, cmd[0]);
		r->status = SDcheck;
		return SDcheck;
	}

	if(r->data == nil)
		return SDok;

	if(r->clen == 16){
		if(cmd[2] || cmd[3])
			return sdsetsense(r, SDcheck, 3, 0xc, 2);
		lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32;
		lba |=   cmd[6]<<24 |  cmd[7]<<16 |  cmd[8]<<8 | cmd[9];
		count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13];
	}else{
		lba  = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
		count = cmd[7]<<8 | cmd[8];
	}

	count *= Aoesectsz;

	if(r->dlen < count)
		count = r->dlen & ~0x1ff;

	if(waserror()){
		if(strcmp(up->errstr, Echange) == 0 ||
		    strcmp(up->errstr, Eaoedown) == 0)
			unit->sectors = 0;
		nexterror();
	}
	r->rlen = rio(c->c, r->data, count, Aoesectsz * lba);
	poperror();
	r->status = SDok;
	return SDok;
}
Exemple #7
0
int
sdfakescsi(SDreq *r, void *info, int ilen)
{
	uchar *cmd, *p;
	uvlong len;
	SDunit *unit;

	cmd = r->cmd;
	r->rlen = 0;
	unit = r->unit;

	/*
	 * Rewrite read(6)/write(6) into read(10)/write(10).
	 */
	switch(cmd[0]){
	case 0x08:	/* read */
	case 0x0A:	/* write */
		cmd[9] = 0;
		cmd[8] = cmd[4];
		cmd[7] = 0;
		cmd[6] = 0;
		cmd[5] = cmd[3];
		cmd[4] = cmd[2];
		cmd[3] = cmd[1] & 0x0F;
		cmd[2] = 0;
		cmd[1] &= 0xE0;
		cmd[0] |= 0x20;
		break;
	}

	/*
	 * Map SCSI commands into ATA commands for discs.
	 * Fail any command with a LUN except INQUIRY which
	 * will return 'logical unit not supported'.
	 */
	if((cmd[1]>>5) && cmd[0] != 0x12)
		return sdsetsense(r, SDcheck, 0x05, 0x25, 0);

	switch(cmd[0]){
	default:
		return sdsetsense(r, SDcheck, 0x05, 0x20, 0);

	case 0x00:	/* test unit ready */
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x03:	/* request sense */
		if(cmd[4] < sizeof unit->sense)
			len = cmd[4];
		else
			len = sizeof unit->sense;
		if(r->data && r->dlen >= len){
			memmove(r->data, unit->sense, len);
			r->rlen = len;
		}
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x12:	/* inquiry */
		if(cmd[4] < sizeof unit->inquiry)
			len = cmd[4];
		else
			len = sizeof unit->inquiry;
		if(r->data && r->dlen >= len){
			memmove(r->data, unit->inquiry, len);
			r->rlen = len;
		}
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x1B:	/* start/stop unit */
		/*
		 * nop for now, can use power management later.
		 */
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x25:	/* read capacity */
		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
		if(r->data == nil || r->dlen < 8)
			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);

		/*
		 * Read capacity returns the LBA of the last sector.
		 */
		len = unit->sectors - 1;
		p = r->data;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		len = 512;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		r->rlen = p - (uchar*)r->data;
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x9E:	/* long read capacity */
		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
		if(r->data == nil || r->dlen < 8)
			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
		/*
		 * Read capcity returns the LBA of the last sector.
		 */
		len = unit->sectors - 1;
		p = r->data;
		*p++ = len>>56;
		*p++ = len>>48;
		*p++ = len>>40;
		*p++ = len>>32;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		len = 512;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		r->rlen = p - (uchar*)r->data;
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x5A:	/* mode sense */
		return sdmodesense(r, cmd, info, ilen);

	case 0x28:	/* read */
	case 0x2A:	/* write */
	case 0x88:	/* read16 */
	case 0x8a:	/* write16 */
		return SDnostatus;
	}
}
Exemple #8
0
int
sdfakescsi(SDreq *r)
{
	uchar *cmd, *p;
	uvlong len;
	SDunit *unit;

	cmd = r->cmd;
	r->rlen = 0;
	unit = r->unit;

	/*
	 * Map SCSI commands into ATA commands for discs.
	 * Fail any command with a LUN except INQUIRY which
	 * will return 'logical unit not supported'.
	 */
	if((cmd[1]>>5) && cmd[0] != 0x12)
		return sdsetsense(r, SDcheck, 0x05, 0x25, 0);

	switch(cmd[0]){
	default:
		return sdsetsense(r, SDcheck, 0x05, 0x20, 0);

	case 0x00:	/* test unit ready */
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x03:	/* request sense */
		if(cmd[4] < sizeof unit->sense)
			len = cmd[4];
		else
			len = sizeof unit->sense;
		if(r->data && r->dlen >= len){
			memmove(r->data, unit->sense, len);
			r->rlen = len;
		}
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x12:	/* inquiry */
		if(cmd[4] < sizeof unit->inquiry)
			len = cmd[4];
		else
			len = sizeof unit->inquiry;
		if(r->data && r->dlen >= len){
			memmove(r->data, unit->inquiry, len);
			r->rlen = len;
		}
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x1B:	/* start/stop unit */
		/*
		 * nop for now, can use power management later.
		 */
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x25:	/* read capacity */
		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
		if(r->data == nil || r->dlen < 8)
			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);

		/*
		 * Read capacity returns the LBA of the last sector.
		 */
		len = unit->sectors;
		if(len >= 0xffffffff)
			len = 0xffffffff;
		else if(len > 0)
			len--;
		p = r->data;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		len = unit->secsize;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		r->rlen = p - (uchar*)r->data;
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x9E:	/* long read capacity */
		if((cmd[1] & 0x01) || cmd[2] || cmd[3])
			return sdsetsense(r, SDcheck, 0x05, 0x24, 0);
		if(r->data == nil || r->dlen < 8)
			return sdsetsense(r, SDcheck, 0x05, 0x20, 1);
		/*
		 * Read capcity returns the LBA of the last sector.
		 */
		len = unit->sectors;
		if(len > 0)
			len--;
		p = r->data;
		*p++ = len>>56;
		*p++ = len>>48;
		*p++ = len>>40;
		*p++ = len>>32;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		len = unit->secsize;
		*p++ = len>>24;
		*p++ = len>>16;
		*p++ = len>>8;
		*p++ = len;
		r->rlen = p - (uchar*)r->data;
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x35:	/* synchronize cache */
	case 0x91:
		return sdsetsense(r, SDok, 0, 0, 0);

	case 0x08:	/* read6 */
	case 0x0a:	/* write6 */
	case 0x28:	/* read10 */
	case 0x2a:	/* write10 */
	case 0xa8:	/* read12 */
	case 0xaa:	/* write12 */
	case 0x88:	/* read16 */
	case 0x8a:	/* write16 */
		return SDnostatus;
	}
}