NWR04B: My descent into little-endian binary arithmetic hell

Currently writing this entry in emacs. Once upon a time, I stopped using emacs for fear of what loading a 20MB editor would do to the mail server I was working on, and learned to love vi. Prompted by ESR's Art of Unix Programming, I've decided to try pick up emacs again. It's interesting....Anyhow: Right now I'm trying to figure out why the hell writing to flash on the NWR04B is not working. First off, I've edited the map file for the flash devices (drivers/mtd/maps/cx84200-flash.c for those of you playing the home game) so that I've got two partitions declared:

static struct mtd_partition cx84200_partitions[] = {
        {
                name:           "bootloader",
                size:           0x00020000,
                offset:         0x00000000,
                mask_flags:     MTD_WRITEABLE, /* force read-only */
        }, {
                name:           "root_fs",
                // Codeman's original:
                // size:        0x000fa000,
                // My efforts at making a root partition:
                size:           0x00040000,
                offset:         0x000f0000,
}

The first I'm not really doing anything with, but it could (as the title suggests) be turned into a bootloader partition someday. The second is where I'm concentrating my efforts. The read-only flag that was originally in there was removed once I figured out it might help matters. :-) Okay, so now what? Well, got a jffs2 image that I created, so let's try the obvious:

# cat test.jffs2 > /dev/mtd1

...and it just hangs. (I still haven't bothered to figure out how to make CTRL-C interrupt a process yet...something to do with the terminal, I think.) Up the debugging output and you see MTD_open, and then nothing. I had a look at the part of the driver (drivers/mtd/chips/sst39vf080.c) to see what's going on here, and I managed to figure it out a bit. The write operation tries to write one byte at a time, then reads it back to make sure it got read. If so, move on to the next byte; if not, try 256 more times (I guess waiting to see if it just needs a moment) and see if that works. If yes, next byte; if not, give up on the write entirely. I threw in some messages to track that, and one that shows what value it's reading back from flash after the write. After throwing in ridiculous amounts of debugging info to track this, it seems that the write of the first byte is simply not working. The write fails, and cat just keeps on trying (or something). A bunch of looking around finally turned up the MTD-JFFS-HOWTO from (I think) the guy who wrote the MTD driver. 'S full of all sorts of helpful hints, like:

Well, fuck. So I follow the directions for the 2.4 kernel support, and figure out how to compile the flash_eraseall utility. Wonderful! Ready to go! Just gotta erase this here partition, and... Only no, that doesn't work: I get the same error re: the byte not being written as before. I'm currently throwing in even more unholy amounts of debugging than before, and teaching myself the simplest bits of binary arithmetic you can image, in order to confirm that, yes, write protection is being turned off...I think. This little-endian thing still confuses the hell out of me. The datasheet sez that, at the address the enable_write() operation is accessing, there are 32 bits set aside for controlling the first bank of flash (which is what we're after here). The 26th bit is write-protect (1 for on, 0 for off). enable_write() reads all 32 bits at that address, &'s it with 0x04000000, and then WP should be off. So the unholy debugging shows that the long int being read:

Okay, so that works. Maybe I'll give the flashcp utility (part of the MTD tree) a try and see how that goes.