/*****************************************************************************/
#define CMD_ATM_READY 0x22
-#define CMD_SEC_GET_NAME 'G' /* read filename */
+#define CMD_SEC_GET_NAME 'G' /* filename r/w */
+#define CMD_SEC_PUT_NAME 'P'
+#define CMD_SEC_DEVID 'L' /* read flash device ID */
+#define CMD_SEC_ERASE 'E'
+#define CMD_SEC_READY 'C' /* is flash ready? */
/* bus controllers */
#define CTL_DATA_BUS 0x55
#define CTL_ADDR_BUS 0xAA
+#define W_COUNTER 0xA0
+#define W_CNT_WRITE 0x01
+#define W_CNT_READ 0x00
+
#define FILENAME_ROM0 0
#define FILENAME_ROM1 1
#define FILENAME_RAM 2
typedef struct {
u8 magic[4];
- u8 reserved[11];
+ u8 reserved[8];
+ u8 write_flag;
+ u8 reserved2[2];
u8 magic2;
u8 mx_cmd;
union {
u8 which;
} filename;
struct {
- u8 times_cmd;
+ u8 cmd;
u8 action;
- u8 cntb3;
- u8 cntb2;
- u8 cntb1;
- u8 cntb0;
- } times_write;
+ u8 b0;
+ u8 b1;
+ u8 b2;
+ u8 b3;
+ } write_cnt;
+ struct {
+ u8 which;
+ u8 dev_id;
+ } rom_id;
};
u8 pad[8];
} dev_cmd_t;
char names[56];
} dev_info_t;
+typedef struct {
+ u32 start_addr;
+ u32 end_addr;
+ u32 page_size;
+} page_table_t;
+
+static const page_table_t p_AM29LV320DB[] =
+{
+ { 0x000000, 0x00ffff, 0x002000 },
+ { 0x010000, 0x3fffff, 0x010000 },
+ { 0x000000, 0x000000, 0x000000 },
+};
+
+static const page_table_t p_AM29LV320DT[] =
+{
+ { 0x000000, 0x3effff, 0x010000 },
+ { 0x3f0000, 0x3fffff, 0x002000 },
+ { 0x000000, 0x000000, 0x000000 },
+};
+
+/*****************************************************************************/
+
static void prepare_cmd(dev_cmd_t *dev_cmd, u8 cmd)
{
memset(dev_cmd, 0, sizeof(*dev_cmd));
dev_cmd->mx_cmd = cmd;
}
-static int write_cmd(struct usb_dev_handle *dev, dev_cmd_t *cmd)
+static int write_data(struct usb_dev_handle *dev, void *data, int len)
{
- int ret = usb_bulk_write(dev, 0x03, (char *)cmd, sizeof(*cmd), 2000);
+ int ret = usb_bulk_write(dev, 0x03, data, len, 2000);
if (ret < 0) {
fprintf(stderr, "failed to write:\n");
fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
- } else if (ret != sizeof(*cmd))
- printf("write_cmd: wrote only %d of %d bytes\n", ret, sizeof(*cmd));
+ } else if (ret != len)
+ printf("write_cmd: wrote only %d of %d bytes\n", ret, len);
return ret;
}
-static int read_response(struct usb_dev_handle *dev, void *buff, int size)
+static int write_cmd(struct usb_dev_handle *dev, dev_cmd_t *cmd)
+{
+ return write_data(dev, cmd, sizeof(*cmd));
+}
+
+static int read_data(struct usb_dev_handle *dev, void *buff, int size)
{
int ret = usb_bulk_read(dev, 0x82, buff, size, 2000);
if (ret < 0) {
fprintf(stderr, "failed to read:\n");
fprintf(stderr, "%s (%d)\n", usb_strerror(), ret);
} else if (ret != size)
- printf("read_response: read only %d of %d bytes\n", ret, size);
+ printf("read_data: read only %d of %d bytes\n", ret, size);
return ret;
}
if (ret < 0)
return ret;
- ret = read_response(device, &info, sizeof(info));
+ ret = read_data(device, &info, sizeof(info));
if (ret < 0)
return ret;
return 0;
}
-static int get_filename(struct usb_dev_handle *dev, char *dst, int len, u8 which)
+static int read_filename(struct usb_dev_handle *dev, char *dst, int len, u8 which)
{
char buff[65];
dev_cmd_t cmd;
if (ret < 0)
return ret;
- ret = read_response(dev, buff, 64);
+ ret = read_data(dev, buff, 64);
if (ret < 0)
return ret;
return 0;
}
+static int write_filename(struct usb_dev_handle *dev, const char *fname, u8 which)
+{
+ dev_cmd_t cmd;
+ char buff[64];
+ int ret, len;
+
+ len = strlen(fname);
+ if (len > 63)
+ len = 63;
+ strncpy(buff, fname, len);
+ buff[len] = 0;
+
+ prepare_cmd(&cmd, CMD_SEC_PUT_NAME);
+ cmd.filename.which = which;
+
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ return write_data(dev, buff, len + 1);
+}
+
+static int read_w_counter(struct usb_dev_handle *dev, u32 *val)
+{
+ dev_cmd_t cmd;
+ u8 buff[16];
+ int ret;
+
+ prepare_cmd(&cmd, CMD_ATM_READY);
+ cmd.write_cnt.cmd = W_COUNTER;
+ cmd.write_cnt.action = W_CNT_READ;
+
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = read_data(dev, buff, sizeof(buff));
+ if (ret < 0)
+ return ret;
+
+ *val = *(u32 *)buff;
+ return 0;
+}
+
+static int read_flash_rom_id(struct usb_dev_handle *dev, u32 *val)
+{
+ dev_cmd_t cmd;
+ u8 buff[2];
+ int ret;
+
+ prepare_cmd(&cmd, CMD_SEC_DEVID);
+ cmd.write_flag = 1; /* XXX why? */
+ cmd.rom_id.dev_id = 1;
+ cmd.rom_id.which = 0;
+
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = read_data(dev, buff, sizeof(buff));
+ if (ret < 0)
+ return ret;
+
+ *val = *(u16 *)buff << 16;
+
+ cmd.rom_id.which = 0;
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = read_data(dev, buff, sizeof(buff));
+ if (ret < 0)
+ return ret;
+
+ *val |= *(u16 *)buff;
+ return 0;
+}
+
+static const page_table_t *get_page_table(u32 rom_id)
+{
+ switch (rom_id) {
+ case 0x0100F922:
+ return p_AM29LV320DB;
+ case 0x0100F422:
+ return p_AM29LV320DT;
+ default:
+ fprintf(stderr, "unrecognized ROM id: %08x\n", rom_id);
+ }
+
+ return NULL;
+}
+
+static int get_page_size(const page_table_t *table, u32 addr, u32 *size)
+{
+ const page_table_t *t;
+
+ for (t = table; t->end_addr != 0; t++) {
+ if (addr >= t->start_addr && addr <= t->end_addr) {
+ *size = t->page_size;
+ return 0;
+ }
+ }
+
+ if (addr == t[-1].end_addr + 1)
+ return 1; /* last */
+
+ fprintf(stderr, "get_page_size: failed on addr %06x\n", addr);
+ return -1;
+}
+
+static int erase_sector(struct usb_dev_handle *dev, u32 addr)
+{
+ dev_cmd_t cmd;
+ u8 buff[10];
+ int i, ret;
+
+ prepare_cmd(&cmd, CMD_SEC_ERASE);
+ cmd.write_flag = 1;
+ cmd.rom_rw.addrb2 = addr >> 16;
+ cmd.rom_rw.addrb1 = addr >> 8;
+ cmd.rom_rw.addrb0 = addr;
+
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = read_data(dev, buff, sizeof(buff));
+ if (ret < 0)
+ return ret;
+
+ prepare_cmd(&cmd, CMD_SEC_READY);
+ cmd.rom_rw.addrb2 = addr >> 16;
+ cmd.rom_rw.addrb1 = addr >> 8;
+ cmd.rom_rw.addrb0 = addr;
+
+ for (i = 0; i < 100; i++) {
+ ret = write_cmd(dev, &cmd);
+ if (ret < 0)
+ return ret;
+
+ ret = read_data(dev, buff, sizeof(buff));
+ if (ret < 0)
+ return ret;
+
+ if (ret > 4 && buff[4] == 1)
+ break;
+
+ usleep(50);
+ }
+
+ printf("i = %d\n", i);
+ return 0;
+}
+
static usb_dev_handle *get_device(void)
{
struct usb_dev_handle *handle;
{
struct usb_dev_handle *device;
char fname[65];
+ u32 counter, rom_id;
int ret;
usb_init();
if (ret < 0)
goto end;
- ret = get_filename(device, fname, sizeof(fname), FILENAME_ROM0);
+ ret = read_filename(device, fname, sizeof(fname), FILENAME_ROM0);
if (ret < 0)
goto end;
printf("ROM filename: %s\n", fname);
- ret = get_filename(device, fname, sizeof(fname), FILENAME_RAM);
+ ret = read_filename(device, fname, sizeof(fname), FILENAME_RAM);
if (ret < 0)
goto end;
printf("SRAM filename: %s\n", fname);
+ ret = read_w_counter(device, &counter);
+ if (ret < 0)
+ goto end;
+ printf("flash writes: %u\n", counter);
+ ret = read_flash_rom_id(device, &rom_id);
+ if (ret < 0)
+ goto end;
+ printf("flash rom id: %08x\n", rom_id);
end:
release_device(device);