You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.5 KiB
150 lines
3.5 KiB
#define _GNU_SOURCE
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <spi.h>
|
|
|
|
#include <stdio.h>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <spi_flash.h>
|
|
|
|
// 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);
|
|
|
|
static struct spi_ops virtual_spi_ops = {
|
|
.tx_rx = virtual_spi_tx_rx,
|
|
};
|
|
|
|
// XXX: make part of dev struct
|
|
static unsigned char *flash_map;
|
|
|
|
static int virtual_spi_init(void)
|
|
{
|
|
/* 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)
|
|
{
|
|
struct spi_dev *dev;
|
|
|
|
if (!(dev = malloc(sizeof *dev)))
|
|
return NULL;
|
|
|
|
dev->ops = &virtual_spi_ops;
|
|
/*
|
|
dev->dev_id = SPI1;
|
|
|
|
*/
|
|
if (virtual_spi_init()) {
|
|
free(dev);
|
|
return NULL;
|
|
}
|
|
|
|
return dev;
|
|
}
|
|
|
|
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)
|
|
{
|
|
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;
|
|
}
|
|
|