#include <u.h>#include <libc.h>#include <disk.h>#include <fis.h>#include </sys/src/cmd/scuzz/scsireq.h>#include "dat.h" enum{ Replysz = 16,}; typedef struct Rcmd Rcmd;struct Rcmd{ uchar proto; uchar cdbsz; uchar cdb[16];}; typedef struct Req Req;struct Req { char haverfis; Rcmd cmd; char sdstat[16]; uchar sense[0x100]; uchar data[0x200]; uint count;}; voidturcdb(Req *r){ uchar *cmd; cmd = r->cmd.cdb; r->cmd.cdbsz = 6; r->cmd.proto = Pin; memset(cmd, 0, 6); r->count = 0;} voidreqsensecdb(Req *r){ uchar *cmd; cmd = r->cmd.cdb; r->cmd.cdbsz = 6; r->cmd.proto = Pin; memset(cmd, 0, 6); cmd[0] = ScmdRsense; cmd[4] = 128; r->count = 128;} static voidsensetrace(uchar *cdb, uchar *u){ char *e; USED(cdb); if(1) return; e = scsierror(u[12], u[13]); fprint(2, "sense %.2ux: %.2ux%.2ux%.2ux %s\n", cdb[0], u[2], u[12], u[13], e);} static intissuescsi(Req *r, Sdisk *d){ uchar *u; int ok, rv, n; Req sense; if(write(d->fd, r->cmd.cdb, r->cmd.cdbsz) != r->cmd.cdbsz){ eprint(d, "cdb write error: %r\n"); return -1; } werrstr(""); switch(r->cmd.proto){ default: case Pin: n = read(d->fd, r->data, r->count); ok = n >= 0; r->count = 0; if(ok) r->count = n; break; case Pout: n = write(d->fd, r->data, r->count); ok = n == r->count; break; } rv = 0; memset(r->sdstat, 0, sizeof r->sdstat); if(read(d->fd, r->sdstat, Replysz) < 1){ eprint(d, "status reply read error: %r\n"); return -1; } if(n == -1) rv = -1; /* scsi not supported; don't whine */ else if(rv == 0 && (rv = atoi(r->sdstat)) != 0){ memset(&sense, 0, sizeof sense); reqsensecdb(&sense); if(issuescsi(&sense, d) == 0){ memmove(r->sense, sense.data, sense.count); u = r->sense; rv = u[2]; sensetrace(r->cmd.cdb, u); }else rv = -1; } return ok? rv: -1;} voidmodesensecdb(Req *r, uchar page, uint n){ uchar *cmd; cmd = r->cmd.cdb; r->cmd.cdbsz = 10; r->cmd.proto = Pin; memset(cmd, 0, 10); cmd[0] = ScmdMsense10; cmd[2] = page; cmd[7] = n>>8; cmd[8] = n; r->count = n;} voidmodeselectcdb(Req *r, uint n){ uchar *cmd; cmd = r->cmd.cdb; r->cmd.proto = Pout; r->cmd.cdbsz = 10; memset(cmd, 0, 10); cmd[0] = ScmdMselect10; cmd[1] = 0x10; /* assume scsi2 ! */ cmd[7] = n>>8; cmd[8] = n; r->count = n;} intscsiprobe(Sdisk *d){ Req r; memset(&r, 0, sizeof r); turcdb(&r); if(issuescsi(&r, d) == -1) return -1; memset(&r, 0, sizeof r); modesensecdb(&r, 0x1c, sizeof r.data); if(issuescsi(&r, d) != 0 || r.count < 8) return -1; return 0;}
#include <u.h>
#include <libc.h>
#include <disk.h>
#include <fis.h>
#include </sys/src/cmd/scuzz/scsireq.h>
#include "dat.h"
enum{
Replysz = 16,
};
typedef struct Rcmd Rcmd;
struct Rcmd{
uchar proto;
uchar cdbsz;
uchar cdb[16];
};
typedef struct Req Req;
struct Req {
char haverfis;
Rcmd cmd;
char sdstat[16];
uchar sense[0x100];
uchar data[0x200];
uint count;
};
void
turcdb(Req *r)
{
uchar *cmd;
cmd = r->cmd.cdb;
r->cmd.cdbsz = 6;
r->cmd.proto = Pin;
memset(cmd, 0, 6);
r->count = 0;
}
void
reqsensecdb(Req *r)
{
uchar *cmd;
cmd = r->cmd.cdb;
r->cmd.cdbsz = 6;
r->cmd.proto = Pin;
memset(cmd, 0, 6);
cmd[0] = ScmdRsense;
cmd[4] = 128;
r->count = 128;
}
static void
sensetrace(uchar *cdb, uchar *u)
{
char *e;
USED(cdb);
if(1)
return;
e = scsierror(u[12], u[13]);
fprint(2, "sense %.2ux: %.2ux%.2ux%.2ux %s\n", cdb[0], u[2], u[12], u[13], e);
}
static int
issuescsi(Req *r, Sdisk *d)
{
uchar *u;
int ok, rv, n;
Req sense;
if(write(d->fd, r->cmd.cdb, r->cmd.cdbsz) != r->cmd.cdbsz){
eprint(d, "cdb write error: %r\n");
return -1;
}
werrstr("");
switch(r->cmd.proto){
default:
case Pin:
n = read(d->fd, r->data, r->count);
ok = n >= 0;
r->count = 0;
if(ok)
r->count = n;
break;
case Pout:
n = write(d->fd, r->data, r->count);
ok = n == r->count;
break;
}
rv = 0;
memset(r->sdstat, 0, sizeof r->sdstat);
if(read(d->fd, r->sdstat, Replysz) < 1){
eprint(d, "status reply read error: %r\n");
return -1;
}
if(n == -1)
rv = -1; /* scsi not supported; don't whine */
else if(rv == 0 && (rv = atoi(r->sdstat)) != 0){
memset(&sense, 0, sizeof sense);
reqsensecdb(&sense);
if(issuescsi(&sense, d) == 0){
memmove(r->sense, sense.data, sense.count);
u = r->sense;
rv = u[2];
sensetrace(r->cmd.cdb, u);
}else
rv = -1;
}
return ok? rv: -1;
}
void
modesensecdb(Req *r, uchar page, uint n)
{
uchar *cmd;
cmd = r->cmd.cdb;
r->cmd.cdbsz = 10;
r->cmd.proto = Pin;
memset(cmd, 0, 10);
cmd[0] = ScmdMsense10;
cmd[2] = page;
cmd[7] = n>>8;
cmd[8] = n;
r->count = n;
}
void
modeselectcdb(Req *r, uint n)
{
uchar *cmd;
cmd = r->cmd.cdb;
r->cmd.proto = Pout;
r->cmd.cdbsz = 10;
memset(cmd, 0, 10);
cmd[0] = ScmdMselect10;
cmd[1] = 0x10; /* assume scsi2 ! */
cmd[7] = n>>8;
cmd[8] = n;
r->count = n;
}
int
scsiprobe(Sdisk *d)
{
Req r;
memset(&r, 0, sizeof r);
turcdb(&r);
if(issuescsi(&r, d) == -1)
return -1;
memset(&r, 0, sizeof r);
modesensecdb(&r, 0x1c, sizeof r.data);
if(issuescsi(&r, d) != 0 || r.count < 8)
return -1;
return 0;
}