#include <u.h>#include <libc.h>#include <fis.h>#include "atazz.h"#include "tabs.h" #pragma varargck argpos eprint 1#pragma varargck type "π" char** enum { Dontread = -2,}; int interrupted;int rflag;int squelch;int scttrace;uchar issuetr[0x100]; Atatab *idcmd;Atatab *idpktcmd;Atatab *sigcmd;Atatab *sctread;Atatab *sctissue; intπfmt(Fmt *f){ char **p; p = va_arg(f->args, char**); if(p == nil) return fmtstrcpy(f, "<nil**>"); for(; *p; p++){ fmtstrcpy(f, *p); if(p[1] != nil) fmtstrcpy(f, " "); } return 0;} inteprint(char *fmt, ...){ int n; va_list args; if(squelch) return 0;// Bflush(&out); va_start(args, fmt); n = vfprint(2, fmt, args); va_end(args); return n;} voidfisset(Req *r, uint i, uint v){ if(r->fisbits & 1<<i) return; r->fisbits |= 1<<i; r->cmd.fis[i] = v;} voidprreq(Req *r){ uchar *u; print("%.2ux %.2ux\n", r->cmd.sdcmd, r->cmd.ataproto); u = r->cmd.fis; print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux ", u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]); u += 8; print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux\n", u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]);} char*protostr(char *p, char *e, int pr){ char *s; *p = 0; if(pr & P28) p = seprint(p, e, "28:"); else p = seprint(p, e, "28:"); switch(pr & Pprotom){ default: s = "unk"; break; case Ppkt: s = "pkt"; break; case Pdiag: s = "dig"; break; case Preset: s = "rst"; break; case Pdmq: s = "dmq"; break; case Pdma: s = "dma"; break; case Ppio: s = "pio"; break; } p = seprint(p, e, "%s:", s); switch(pr & Pdatam){ default: s = "nd"; break; case Pin: s = "in"; break; case Pout: s = "out"; break; } p = seprint(p, e, "%s", s); return p;} voiddisplaycmd(Req *r, Atatab *a){ char buf[32]; int i; if(a->cc > nelem(issuetr) || !issuetr[a->cc]) return; protostr(buf, buf + sizeof buf, a->protocol); fprint(2, "cmd %s:%2ux ", buf, a->cc); for(i = 0; i < 16; i++) fprint(2, "%.2ux", r->cmd.fis[i]); fprint(2, "\n");} intissueata(Req *r, Atatab *a, Dev *d){ uchar u; int n, ok, pr, rv; r->haverfis = 0; pr = a->protocol & Pdatam; r->data = realloc(r->data, r->count); if(r->data == nil && r->count > 0) sysfatal("realloc: %r"); if(r->data == nil && pr != Pnd) sysfatal("no data for cmd %.2ux", a->cc); if(0 && r->fisbits) print("fisbits %.16b\n", r->fisbits); r->cmd.sdcmd = 0xff; r->cmd.ataproto = a->protocol; if(a->cc & 0xff00) fisset(r, 0, a->cc >> 8); else fisset(r, 0, H2dev); fisset(r, 1, Fiscmd); fisset(r, 2, a->cc); switch(pr){ case Pout: if(r->rfd != Dontread){ n = readn(r->rfd, r->data, r->count); if(n != r->count){ if(n == -1) eprint("!short src read %r\n"); else eprint("!short src read %d wanted %lld\n", n, r->count); return -1; } } case Pnd: case Pin: if(0 && (d->feat & Dlba) == 0 && (d->c | d->h | d->s)){ int c, h, s; c = r->lba / (d->s * d->h); h = (r->lba / d->s) % d->h; s = (r->lba % d->s) + 1;fprint(2, "chs: %d %d %d\n", c, h, s); fisset(r, 4, s); fisset(r, 5, c); fisset(r, 6, c >> 8); fisset(r, 7, Ataobs | h); }else{ fisset(r, 4, r->lba); fisset(r, 5, r->lba >> 8); fisset(r, 6, r->lba >> 16); u = Ataobs; if(pr == Pin || pr == Pout) u |= Atalba; if((d->feat & Dllba) == 0) u |= (r->lba >> 24) & 7; fisset(r, 7, u); fisset(r, 8, r->lba >> 24); fisset(r, 9, r->lba >> 32); fisset(r, 10, r->lba >> 48); } fisset(r, 12, r->nsect); fisset(r, 13, r->nsect >> 8); break; } fisset(r, 7, Ataobs); displaycmd(r, a); if(write(d->fd, &r->cmd, Cmdsz) != Cmdsz){ eprint("fis write error: %r\n"); return -1; } werrstr(""); switch(pr){ default: ok = read(d->fd, "", 0) == 0; break; case Pin: ok = read(d->fd, r->data, r->count) == r->count; r->lba += r->nsect; break; case Pout: ok = write(d->fd, r->data, r->count) == r->count; r->lba += r->nsect; break; } rv = 0; if(ok == 0){ eprint("xfer error: %.2ux %r\n", a->cc); rv = -1; } switch(n = read(d->fd, &r->reply, Replysz)){ case Replysz: r->haverfis = 1; return rv; case -1: eprint("status fis read error: %r\n"); return -1; default: eprint("status fis read error: short read: %d of %d\n", n, Replysz); return -1; }} /* * cheezy code; just issue a inquiry. use scuzz * for real work with atapi devices */intissuepkt(Req *r, Atatab *a, Dev *d){ char *p; uchar *u; int n, rv; r->haverfis = 0; r->count = 128; r->data = realloc(r->data, r->count); if(r->data == nil && r->count > 0) sysfatal("realloc: %r"); r->cmd.sdcmd = 0xff; r->cmd.ataproto = a->protocol; memset(r->cmd.fis, 0, Fissize); u = r->cmd.fis; u[0] = 0x12; u[4] = 128-1; displaycmd(r, a); if(write(d->fd, &r->cmd, 6 + 2) != 6 + 2){ eprint("fis write error: %r\n"); return -1; } n = read(d->fd, r->data, r->count); rv = 0; if(n == -1){ eprint("xfer error: %.2ux %r\n", a->cc); rv = -1; } print("n is %d (%lld)\n", n, r->count); if(n > 32){ p = (char*)r->data; print("%.8s %.16s\n", p + 8, p + 16); } u = (uchar*)&r->reply; n = read(d->fd, u, Replysz); if(n < 0){ eprint("status fis read error (%d): %r\n", n); return -1; } if(n < Replysz) memset(u + n, 0, Replysz - n); r->haverfis = 1; return rv;} /* * silly protocol: * 1. use write log ext 0xe0 to fill out the command * 2. use write log ext 0xe1 to write or data (if any) * 3. use read log ext 0xe0 to nab status. polled */voidsctreq(Req *r){ memset(r, 0, sizeof *r); r->rfd = Dontread;} char*sctrsp(Req *r){ uint i; static char buf[32]; if(!r->haverfis) return "no rfis"; if((r->reply.fis[Frerror] & (Eidnf | Eabrt)) == 0) return nil; i = r->reply.fis[Fsc] | r->reply.fis[Flba0]<<8; if(i == 0xffff) return "in progress"; else if(i == 0){ snprint(buf, sizeof buf, "unknown %.2ux", r->reply.fis[Frerror]); return buf; }else if(i < nelem(sctetab)) return sctetab[i]; else return "<bad>";} char*sctready(Dev *d, int sec){ char *s; int i; Req r; static char e[ERRMAX]; for(;;){ if(interrupted){ s = "interrupted"; break; } sctreq(&r); fisset(&r, Fsc, 1); fisset(&r, Flba0, 0xe0); r.count = 512; i = issueata(&r, sctread, d); free(r.data); if(i == -1){ rerrstr(e, ERRMAX); s = e; break; } if((r.cmd.fis[Fsc] | r.cmd.fis[Fsc8]<<8) != 0xffff){ s = sctrsp(&r); break; } if(sec == 0){ s = "timeout"; break; } sleep(1000); sec--; } return s;} typedef struct Sttab Sttab;struct Sttab { int o; int sz; char *name;}; Sttab sctt[] = { 0, 2, "version", 2, 2, "period", 4, 2, "intval", 6, 1, "max op", 7, 1, "max", 8, 1, "min op", 9, 1, "min",}; voidsctttab(Req *r){ char c, buf[10]; int i, n, l, d; uchar *u; u = r->data; for(i = 0; i < nelem(sctt); i++){ switch(sctt[i].sz){ case 1: c = u[sctt[i].o]; print("%s\t%d\n", sctt[i].name, c); break; case 2: d = w(u + sctt[i].o); print("%s\t%ud\n", sctt[i].name, d); break; } } n = w(u + 30); l = w(u + 32); for(i = 0; i < n; i++){ c = u[34 + (l + i) % n]; if((uchar)c == 0x80) snprint(buf, sizeof buf, "xx"); else snprint(buf, sizeof buf, "%d", c); d = i%10; if(d == 0) print("\nt%d\t%d", i, c); else print("% .2d", c); } if(i%10) print("\n");} static struct { uint code; char *s; char *ms;} fxtab[] = { 0x00010001, "set features", 0, 0x00010002, "enabled", 0, 0x00010003, "disabled", 0, 0x00020001, "enabled", 0, 0x00020002, "disabled", 0, 0x0003ffff, "minute", "minutes",}; voidsctfcout(ushort *u, Req *r){ uchar *f; ushort v; uint c, m, i; f = r->reply.fis; switch(u[1]){ case 1: case 2: v = f[Fsc] | f[Flba0]<<8; c = u[2]<<16 | v; m = u[2]<<16 | 0xffff; for(i = 0; i < nelem(fxtab); i++) if(fxtab[i].code == c) print("%s\n", fxtab[i].s); else if(fxtab[i].code == m) print("%d %s\n", v, v>1? fxtab[i].ms: fxtab[i].s); break; case 3: v = f[Fsc] | f[Flba0]<<8; if(v & 1) print("preserve\n"); else print("volatile\n"); break; }} voidscterout(ushort *u, Req *r){ uchar *f; uint v; f = r->reply.fis; switch(u[1]){ case 2: v = f[Fsc] | f[Flba0]<<8; v *= 100; print("%dms\n", v); }} voidsctout(ushort *u, Req *r){ switch(u[0]){ case 5: sctttab(r); break; case 4: sctfcout(u, r);Lines 1–500 of 1918. Load more
#include <u.h> #include <libc.h> #include <fis.h> #include "atazz.h" #include "tabs.h" #pragma varargck argpos eprint 1 #pragma varargck type "π" char** enum { Dontread = -2, }; int interrupted; int rflag; int squelch; int scttrace; uchar issuetr[0x100]; Atatab *idcmd; Atatab *idpktcmd; Atatab *sigcmd; Atatab *sctread; Atatab *sctissue; int πfmt(Fmt *f) { char **p; p = va_arg(f->args, char**); if(p == nil) return fmtstrcpy(f, "<nil**>"); for(; *p; p++){ fmtstrcpy(f, *p); if(p[1] != nil) fmtstrcpy(f, " "); } return 0; } int eprint(char *fmt, ...) { int n; va_list args; if(squelch) return 0; // Bflush(&out); va_start(args, fmt); n = vfprint(2, fmt, args); va_end(args); return n; } void fisset(Req *r, uint i, uint v) { if(r->fisbits & 1<<i) return; r->fisbits |= 1<<i; r->cmd.fis[i] = v; } void prreq(Req *r) { uchar *u; print("%.2ux %.2ux\n", r->cmd.sdcmd, r->cmd.ataproto); u = r->cmd.fis; print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux ", u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]); u += 8; print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux\n", u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]); } char* protostr(char *p, char *e, int pr) { char *s; *p = 0; if(pr & P28) p = seprint(p, e, "28:"); else p = seprint(p, e, "28:"); switch(pr & Pprotom){ default: s = "unk"; break; case Ppkt: s = "pkt"; break; case Pdiag: s = "dig"; break; case Preset: s = "rst"; break; case Pdmq: s = "dmq"; break; case Pdma: s = "dma"; break; case Ppio: s = "pio"; break; } p = seprint(p, e, "%s:", s); switch(pr & Pdatam){ default: s = "nd"; break; case Pin: s = "in"; break; case Pout: s = "out"; break; } p = seprint(p, e, "%s", s); return p; } void displaycmd(Req *r, Atatab *a) { char buf[32]; int i; if(a->cc > nelem(issuetr) || !issuetr[a->cc]) return; protostr(buf, buf + sizeof buf, a->protocol); fprint(2, "cmd %s:%2ux ", buf, a->cc); for(i = 0; i < 16; i++) fprint(2, "%.2ux", r->cmd.fis[i]); fprint(2, "\n"); } int issueata(Req *r, Atatab *a, Dev *d) { uchar u; int n, ok, pr, rv; r->haverfis = 0; pr = a->protocol & Pdatam; r->data = realloc(r->data, r->count); if(r->data == nil && r->count > 0) sysfatal("realloc: %r"); if(r->data == nil && pr != Pnd) sysfatal("no data for cmd %.2ux", a->cc); if(0 && r->fisbits) print("fisbits %.16b\n", r->fisbits); r->cmd.sdcmd = 0xff; r->cmd.ataproto = a->protocol; if(a->cc & 0xff00) fisset(r, 0, a->cc >> 8); else fisset(r, 0, H2dev); fisset(r, 1, Fiscmd); fisset(r, 2, a->cc); switch(pr){ case Pout: if(r->rfd != Dontread){ n = readn(r->rfd, r->data, r->count); if(n != r->count){ if(n == -1) eprint("!short src read %r\n"); else eprint("!short src read %d wanted %lld\n", n, r->count); return -1; } } case Pnd: case Pin: if(0 && (d->feat & Dlba) == 0 && (d->c | d->h | d->s)){ int c, h, s; c = r->lba / (d->s * d->h); h = (r->lba / d->s) % d->h; s = (r->lba % d->s) + 1; fprint(2, "chs: %d %d %d\n", c, h, s); fisset(r, 4, s); fisset(r, 5, c); fisset(r, 6, c >> 8); fisset(r, 7, Ataobs | h); }else{ fisset(r, 4, r->lba); fisset(r, 5, r->lba >> 8); fisset(r, 6, r->lba >> 16); u = Ataobs; if(pr == Pin || pr == Pout) u |= Atalba; if((d->feat & Dllba) == 0) u |= (r->lba >> 24) & 7; fisset(r, 7, u); fisset(r, 8, r->lba >> 24); fisset(r, 9, r->lba >> 32); fisset(r, 10, r->lba >> 48); } fisset(r, 12, r->nsect); fisset(r, 13, r->nsect >> 8); break; } fisset(r, 7, Ataobs); displaycmd(r, a); if(write(d->fd, &r->cmd, Cmdsz) != Cmdsz){ eprint("fis write error: %r\n"); return -1; } werrstr(""); switch(pr){ default: ok = read(d->fd, "", 0) == 0; break; case Pin: ok = read(d->fd, r->data, r->count) == r->count; r->lba += r->nsect; break; case Pout: ok = write(d->fd, r->data, r->count) == r->count; r->lba += r->nsect; break; } rv = 0; if(ok == 0){ eprint("xfer error: %.2ux %r\n", a->cc); rv = -1; } switch(n = read(d->fd, &r->reply, Replysz)){ case Replysz: r->haverfis = 1; return rv; case -1: eprint("status fis read error: %r\n"); return -1; default: eprint("status fis read error: short read: %d of %d\n", n, Replysz); return -1; } } /* * cheezy code; just issue a inquiry. use scuzz * for real work with atapi devices */ int issuepkt(Req *r, Atatab *a, Dev *d) { char *p; uchar *u; int n, rv; r->haverfis = 0; r->count = 128; r->data = realloc(r->data, r->count); if(r->data == nil && r->count > 0) sysfatal("realloc: %r"); r->cmd.sdcmd = 0xff; r->cmd.ataproto = a->protocol; memset(r->cmd.fis, 0, Fissize); u = r->cmd.fis; u[0] = 0x12; u[4] = 128-1; displaycmd(r, a); if(write(d->fd, &r->cmd, 6 + 2) != 6 + 2){ eprint("fis write error: %r\n"); return -1; } n = read(d->fd, r->data, r->count); rv = 0; if(n == -1){ eprint("xfer error: %.2ux %r\n", a->cc); rv = -1; } print("n is %d (%lld)\n", n, r->count); if(n > 32){ p = (char*)r->data; print("%.8s %.16s\n", p + 8, p + 16); } u = (uchar*)&r->reply; n = read(d->fd, u, Replysz); if(n < 0){ eprint("status fis read error (%d): %r\n", n); return -1; } if(n < Replysz) memset(u + n, 0, Replysz - n); r->haverfis = 1; return rv; } /* * silly protocol: * 1. use write log ext 0xe0 to fill out the command * 2. use write log ext 0xe1 to write or data (if any) * 3. use read log ext 0xe0 to nab status. polled */ void sctreq(Req *r) { memset(r, 0, sizeof *r); r->rfd = Dontread; } char* sctrsp(Req *r) { uint i; static char buf[32]; if(!r->haverfis) return "no rfis"; if((r->reply.fis[Frerror] & (Eidnf | Eabrt)) == 0) return nil; i = r->reply.fis[Fsc] | r->reply.fis[Flba0]<<8; if(i == 0xffff) return "in progress"; else if(i == 0){ snprint(buf, sizeof buf, "unknown %.2ux", r->reply.fis[Frerror]); return buf; }else if(i < nelem(sctetab)) return sctetab[i]; else return "<bad>"; } char* sctready(Dev *d, int sec) { char *s; int i; Req r; static char e[ERRMAX]; for(;;){ if(interrupted){ s = "interrupted"; break; } sctreq(&r); fisset(&r, Fsc, 1); fisset(&r, Flba0, 0xe0); r.count = 512; i = issueata(&r, sctread, d); free(r.data); if(i == -1){ rerrstr(e, ERRMAX); s = e; break; } if((r.cmd.fis[Fsc] | r.cmd.fis[Fsc8]<<8) != 0xffff){ s = sctrsp(&r); break; } if(sec == 0){ s = "timeout"; break; } sleep(1000); sec--; } return s; } typedef struct Sttab Sttab; struct Sttab { int o; int sz; char *name; }; Sttab sctt[] = { 0, 2, "version", 2, 2, "period", 4, 2, "intval", 6, 1, "max op", 7, 1, "max", 8, 1, "min op", 9, 1, "min", }; void sctttab(Req *r) { char c, buf[10]; int i, n, l, d; uchar *u; u = r->data; for(i = 0; i < nelem(sctt); i++){ switch(sctt[i].sz){ case 1: c = u[sctt[i].o]; print("%s\t%d\n", sctt[i].name, c); break; case 2: d = w(u + sctt[i].o); print("%s\t%ud\n", sctt[i].name, d); break; } } n = w(u + 30); l = w(u + 32); for(i = 0; i < n; i++){ c = u[34 + (l + i) % n]; if((uchar)c == 0x80) snprint(buf, sizeof buf, "xx"); else snprint(buf, sizeof buf, "%d", c); d = i%10; if(d == 0) print("\nt%d\t%d", i, c); else print("% .2d", c); } if(i%10) print("\n"); } static struct { uint code; char *s; char *ms; } fxtab[] = { 0x00010001, "set features", 0, 0x00010002, "enabled", 0, 0x00010003, "disabled", 0, 0x00020001, "enabled", 0, 0x00020002, "disabled", 0, 0x0003ffff, "minute", "minutes", }; void sctfcout(ushort *u, Req *r) { uchar *f; ushort v; uint c, m, i; f = r->reply.fis; switch(u[1]){ case 1: case 2: v = f[Fsc] | f[Flba0]<<8; c = u[2]<<16 | v; m = u[2]<<16 | 0xffff; for(i = 0; i < nelem(fxtab); i++) if(fxtab[i].code == c) print("%s\n", fxtab[i].s); else if(fxtab[i].code == m) print("%d %s\n", v, v>1? fxtab[i].ms: fxtab[i].s); break; case 3: v = f[Fsc] | f[Flba0]<<8; if(v & 1) print("preserve\n"); else print("volatile\n"); break; } } void scterout(ushort *u, Req *r) { uchar *f; uint v; f = r->reply.fis; switch(u[1]){ case 2: v = f[Fsc] | f[Flba0]<<8; v *= 100; print("%dms\n", v); } } void sctout(ushort *u, Req *r) { switch(u[0]){ case 5: sctttab(r); break; case 4: sctfcout(u, r);