#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
/* flash partitions */
typedef struct FlashPart FlashPart;
struct FlashPart
{
QLock;
char name[NAMELEN];
ulong start; /* byte offsets */
ulong end;
};
static ulong *flash = (ulong*)FLASHZERO;
/*
* on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
* accesses, one to the low half of the chip and the other to the high
* half. Therefore for all command accesses, ushort indices in the
* manuals turn into ulong indices in our code. Also, by copying all
* 16 bit commands to both halves of a 32 bit command, we erase 2
* sectors for each request erase request.
*/
/*
* common flash memory interface
*/
struct CFIid
{
ulong q;
ulong r;
ulong y;
ulong cmd_set;
ulong vendor_alg;
ulong ext_alg_addr[2];
ulong alt_cmd_set;
ulong alt_vendor_alg;
ulong alt_ext_ald_addr[2];
};
struct CFIsys
{
ulong vcc_min; /* 100 mv */
ulong vcc_max;
ulong vpp_min;
ulong vpp_max;
ulong word_wr_to; /* 2**n µs */
ulong buf_wr_to; /* 2**n µs */
ulong block_erase_to; /* 2**n ms */
ulong chip_erase_to; /* 2**n ms */
ulong max_word_wr_to; /* 2**n µs */
ulong max_buf_wr_to; /* 2**n µs */
ulong max_block_erase_to; /* 2**n ms */
ulong max_chip_erase_to; /* 2**n ms */
};
struct CFIgeom
{
ulong size; /* 2**n bytes */
ulong dev_code; /* ??? */
ulong max_multi; /* max bytes in a multibyte write */
ulong nregion; /* number of erase regions */
ulong region[1]; /* erase region info */
};
#define mirror(x) (((x)<<16)|(x))
void
cfiquery(void)
{
struct CFIid *id;
flash[0x55] = mirror(0x98);
id = (struct CFIid*)&flash[0x10];
if(id.q != 'q' || id.r != 'r' || id.y != 'y')
print("CFI not supported by flash\n");
flash[0x55] = mirror(0xFF);
}
void
cfigeom(void)
{
}
/*
* flash device interface
*/
enum
{
Qf0=1,
Qf1,
Qf2,
Qf3,
};
Dirtab flashdir[]={
"f0", { Qf0, 0 }, 0, 0664,
"f1", { Qf1, 0 }, 0, 0664,
"f2", { Qf2, 0 }, 0, 0664,
"f3", { Qf3, 0 }, 0, 0664,
};
void
flashinit(void)
{
cfiquery();
cfigeom();
}
static Chan*
flashattach(char* spec)
{
return devattach('r', spec);
}
static int
flashwalk(Chan* c, char* name)
{
return devwalk(c, name, flashdir, nelem(flashdir), devgen);
}
static void
flashstat(Chan* c, char* dp)
{
devstat(c, dp, flashdir, nelem(flashdir), devgen);
}
static Chan*
flashopen(Chan* c, int omode)
{
omode = openmode(omode);
if(strcmp(up->user, eve)!=0)
error(Eperm);
return devopen(c, omode, flashdir, nelem(flashdir), devgen);
}
static void
flashclose(Chan*)
{
}
static long
flashread(Chan* c, void* a, long n, vlong off)
{
USED(c, a, off);
error("UUO");
return n;
}
static long
flashwrite(Chan* c, void* a, long n, vlong)
{
USED(c, a, off);
error("UUO");
return n;
}
Dev flashdevtab = {
'F',
"flash",
devreset,
flashinit,
flashattach,
devclone,
flashwalk,
flashstat,
flashopen,
devcreate,
flashclose,
flashread,
devbread,
flashwrite,
devbwrite,
devremove,
devwstat,
};