19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <fcall.h>
59a747e4fSDavid du Colombier #include <thread.h>
69a747e4fSDavid du Colombier #include <9p.h>
79a747e4fSDavid du Colombier #include "flashfs.h"
89a747e4fSDavid du Colombier
99a747e4fSDavid du Colombier static char* file;
109a747e4fSDavid du Colombier static int fd;
119a747e4fSDavid du Colombier static uchar *ones;
129a747e4fSDavid du Colombier
139a747e4fSDavid du Colombier static int isdev;
149a747e4fSDavid du Colombier
159a747e4fSDavid du Colombier struct {
169a747e4fSDavid du Colombier int dfd; /* data */
179a747e4fSDavid du Colombier int cfd; /* control */
189a747e4fSDavid du Colombier } flash;
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier void
initdata(char * f,int)219a747e4fSDavid du Colombier initdata(char *f, int)
229a747e4fSDavid du Colombier {
239a747e4fSDavid du Colombier char err[ERRMAX];
249a747e4fSDavid du Colombier char buf[1024], *fld[8];
259a747e4fSDavid du Colombier int n;
269a747e4fSDavid du Colombier Dir *d;
279a747e4fSDavid du Colombier
289a747e4fSDavid du Colombier isdev = 1;
299a747e4fSDavid du Colombier flash.dfd = open(f, ORDWR);
309a747e4fSDavid du Colombier if(flash.dfd < 0){
319a747e4fSDavid du Colombier errstr(err, sizeof err);
329a747e4fSDavid du Colombier if((flash.dfd = create(f, ORDWR, 0666)) >= 0){
339a747e4fSDavid du Colombier fprint(2, "warning: created plain file %s\n", buf);
349a747e4fSDavid du Colombier goto Plain;
359a747e4fSDavid du Colombier }
369a747e4fSDavid du Colombier errstr(err, sizeof err); /* restore open error */
379a747e4fSDavid du Colombier sysfatal("opening %s: %r", f);
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier if(snprint(buf, sizeof buf, "%sctl", f) != strlen(f)+3)
409a747e4fSDavid du Colombier sysfatal("path too long: %s", f);
419a747e4fSDavid du Colombier flash.cfd = open(buf, ORDWR);
429a747e4fSDavid du Colombier if(flash.cfd < 0){
439a747e4fSDavid du Colombier fprint(2, "warning: cannot open %s (%r); assuming plain file\n", buf);
449a747e4fSDavid du Colombier Plain:
459a747e4fSDavid du Colombier isdev = 0;
469a747e4fSDavid du Colombier if(sectsize == 0)
479a747e4fSDavid du Colombier sectsize = 512;
489a747e4fSDavid du Colombier if(nsects == 0){
499a747e4fSDavid du Colombier if((d = dirstat(f)) == nil)
509a747e4fSDavid du Colombier sysfatal("stat %s: %r", f);
519a747e4fSDavid du Colombier nsects = d->length / sectsize;
529a747e4fSDavid du Colombier free(d);
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier ones = emalloc9p(sectsize);
559a747e4fSDavid du Colombier memset(ones, ~0, sectsize);
569a747e4fSDavid du Colombier }else{
579a747e4fSDavid du Colombier n = read(flash.cfd, buf, sizeof(buf)-1);
589a747e4fSDavid du Colombier if(n <= 0)
599a747e4fSDavid du Colombier sysfatal("reading %sctl: %r", f);
609a747e4fSDavid du Colombier buf[n] = 0;
619a747e4fSDavid du Colombier n = tokenize(buf, fld, nelem(fld));
629a747e4fSDavid du Colombier if(n < 7)
639a747e4fSDavid du Colombier sysfatal("bad flash geometry");
649a747e4fSDavid du Colombier nsects = atoi(fld[5]);
659a747e4fSDavid du Colombier sectsize = atoi(fld[6]);
669a747e4fSDavid du Colombier if(nsects < 8)
679a747e4fSDavid du Colombier sysfatal("unreasonable value for nsects: %lud", nsects);
689a747e4fSDavid du Colombier if(sectsize < 512)
699a747e4fSDavid du Colombier sysfatal("unreasonable value for sectsize: %lud", sectsize);
709a747e4fSDavid du Colombier }
719a747e4fSDavid du Colombier }
729a747e4fSDavid du Colombier
739a747e4fSDavid du Colombier void
clearsect(int sect)749a747e4fSDavid du Colombier clearsect(int sect)
759a747e4fSDavid du Colombier {
769a747e4fSDavid du Colombier if(isdev==0){
779a747e4fSDavid du Colombier if(pwrite(flash.dfd, ones, sectsize, sect*sectsize) != sectsize)
789a747e4fSDavid du Colombier sysfatal("couldn't erase sector %d: %r", sect);
799a747e4fSDavid du Colombier }else{
809a747e4fSDavid du Colombier if(fprint(flash.cfd, "erase %lud", sect * sectsize) < 0)
819a747e4fSDavid du Colombier sysfatal("couldn't erase sector %d: %r", sect);
829a747e4fSDavid du Colombier }
839a747e4fSDavid du Colombier }
849a747e4fSDavid du Colombier
859a747e4fSDavid du Colombier void
readdata(int sect,void * buff,ulong count,ulong off)869a747e4fSDavid du Colombier readdata(int sect, void *buff, ulong count, ulong off)
879a747e4fSDavid du Colombier {
889a747e4fSDavid du Colombier long n;
899a747e4fSDavid du Colombier ulong m;
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier m = sect * sectsize + off;
929a747e4fSDavid du Colombier n = pread(flash.dfd, buff, count, m);
939a747e4fSDavid du Colombier if(n < 0)
949a747e4fSDavid du Colombier sysfatal("error reading at %lux: %r", m);
959a747e4fSDavid du Colombier if(n != count)
96*14cc0f53SDavid du Colombier sysfatal("short read at %lux, %ld instead of %lud", m, n, count);
979a747e4fSDavid du Colombier }
989a747e4fSDavid du Colombier
999a747e4fSDavid du Colombier int
writedata(int err,int sect,void * buff,ulong count,ulong off)1009a747e4fSDavid du Colombier writedata(int err, int sect, void *buff, ulong count, ulong off)
1019a747e4fSDavid du Colombier {
1029a747e4fSDavid du Colombier long n;
1039a747e4fSDavid du Colombier ulong m;
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier m = sect*sectsize + off;
1069a747e4fSDavid du Colombier n = pwrite(flash.dfd, buff, count, m);
1079a747e4fSDavid du Colombier if(n < 0){
1089a747e4fSDavid du Colombier if(err)
1099a747e4fSDavid du Colombier return 0;
1109a747e4fSDavid du Colombier sysfatal("error writing at %lux: %r", m);
1119a747e4fSDavid du Colombier }
1129a747e4fSDavid du Colombier if(n != count){
1139a747e4fSDavid du Colombier if(err)
1149a747e4fSDavid du Colombier return 0;
1159a747e4fSDavid du Colombier sysfatal("short write at %lud, %ld instead of %lud", m, n, count);
1169a747e4fSDavid du Colombier }
1179a747e4fSDavid du Colombier return 1;
1189a747e4fSDavid du Colombier }
119