diff --git a/source/platform/virtual/spi.c b/source/platform/virtual/spi.c index 13ae1db..b37fc32 100644 --- a/source/platform/virtual/spi.c +++ b/source/platform/virtual/spi.c @@ -4,16 +4,54 @@ #include +#include +#include +#include +#include +#include + +// XXX: 16 is used in other places in this file too +#define FLASH_SIZE (1 << 16) + static int virtual_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len, - const void *tx_buf, size_t tx_len); + const void *tx_buf, size_t tx_len); static struct spi_ops virtual_spi_ops = { .tx_rx = virtual_spi_tx_rx, }; -static void virtual_spi_init(void) +// XXX: make part of dev struct +static unsigned char *flash_map; + +static int virtual_spi_init(void) { - /* TODO */ + /* TODO: close this fd */ + FILE *flash_fd; + int exists = 0; + + exists = access("flash", F_OK) != -1; + /* XXX: treat not existing separately from existing file, since we want to + * null one that doesn't exist yet */ + flash_fd = fopen("flash", "ab+"); + if (!exists) { + fprintf(stderr, + "flash doesn't exist yet, creating and filling now\n"); + char buf[FLASH_SIZE]; + int ret = fwrite(buf, sizeof(char), FLASH_SIZE, flash_fd); + fprintf(stderr, "fwrite ret: %d\n", ret); + } + + if (flash_fd == NULL) { + perror("flash_open"); + fprintf(stderr, "spi init failed\n"); + return 1; + } + flash_map = + mmap(NULL, FLASH_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, + fileno(flash_fd), 0); + fprintf(stderr, "flash: %p\n", flash_map); + + return 0; } struct spi_dev *spi_probe(void) @@ -24,11 +62,14 @@ struct spi_dev *spi_probe(void) return NULL; dev->ops = &virtual_spi_ops; - /* - dev->dev_id = SPI1; + /* + dev->dev_id = SPI1; - */ - virtual_spi_init(); + */ + if (virtual_spi_init()) { + free(dev); + return NULL; + } return dev; } @@ -36,10 +77,74 @@ struct spi_dev *spi_probe(void) void spi_release(struct spi_dev *dev) { free(dev); + /* TODO: close fd, close mmap */ } static int virtual_spi_tx_rx(struct spi_dev *dev, void *rx_buf, size_t rx_len, - const void *tx_buf, size_t tx_len) + const void *tx_buf, size_t tx_len) { + unsigned char *rx_buf_c = (unsigned char *)rx_buf; + unsigned char *tx_buf_c = (unsigned char *)tx_buf; + + unsigned char cmd = tx_buf_c[0]; + + fprintf(stderr, "? RX len: %ld\n", rx_len); + + if (tx_buf != NULL) { + fprintf(stderr, "? TX Command: %d\n", cmd); + fprintf(stderr, "? TX len: %ld\n", tx_len); + if (cmd == SPI_FLASH_JEDEC_ID) { + if (rx_len != 3) { + fprintf(stderr, "UNEXPECTED RX_LEN\n"); + } + fprintf(stderr, "SPI_FLASH_JEDEC_ID\n"); + rx_buf_c[0] = 0x1; + rx_buf_c[1] = 0x1; + rx_buf_c[2] = 16; + } + + if (cmd == SPI_FLASH_READ) { + fprintf(stderr, "SPI_FLASH_READ\n"); + unsigned int addr = (tx_buf_c[1] << 16) + + (tx_buf_c[2] << 8) + tx_buf_c[3]; + fprintf(stderr, "addr: %d\n", addr); + fprintf(stderr, "memmove: %d\n", addr); + memmove(rx_buf_c, flash_map + addr, rx_len); + } + + if (cmd == SPI_FLASH_PAGE_PROGRAM) { + fprintf(stderr, "SPI_FLASH_PAGE_PROGRAM\n"); + unsigned int addr = (tx_buf_c[1] << 16) + + (tx_buf_c[2] << 8) + tx_buf_c[3]; + fprintf(stderr, "addr: %d\n", addr); + fprintf(stderr, "memmove: %d\n", addr); + memmove(flash_map + addr, tx_buf_c + 4, tx_len - 4); + } + + if (cmd == SPI_FLASH_ERASE_4K) { + fprintf(stderr, "SPI_FLASH_ERASE_4K\n"); + unsigned int addr = (tx_buf_c[1] << 16) + + (tx_buf_c[2] << 8) + tx_buf_c[3]; + fprintf(stderr, "addr: %d\n", addr); + memset(flash_map + addr, 0, 4096); + } + + if (cmd == SPI_FLASH_READ_SR1) { + fprintf(stderr, "SPI_FLASH_READ_SR1\n"); + /* Just report read/write/erase as done, we are never busy with mmap */ + rx_buf_c[0] = 0; + } + + if (cmd == SPI_FLASH_WRITE_ENABLE) { + fprintf(stderr, "SPI_FLASH_WRITE_ENABLE\n"); + /* These can be stubs */ + } + + if (cmd == SPI_FLASH_WRITE_DISABLE) { + fprintf(stderr, "SPI_FLASH_WRITE_DISABLE\n"); + /* These can be stubs */ + } + } + return 0; }