From fcc8341738b5e544c004f3644ad578f983b507b3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 15 Mar 2015 16:09:34 +0000 Subject: [PATCH] socz80: poll the ethernet kernel side We don't want to wake/execute user code with context switches each time. TODO: Add a sensible ethernet controller wrapper in VHDL so that it looks like a DMA ethernet controller --- Kernel/platform-socz80/deveth.h | 2 ++ Kernel/platform-socz80/ethernet.c | 39 ++++++++++++++++++++++++++++--- Kernel/platform-socz80/main.c | 5 +++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Kernel/platform-socz80/deveth.h b/Kernel/platform-socz80/deveth.h index 36a43610..3d55122d 100644 --- a/Kernel/platform-socz80/deveth.h +++ b/Kernel/platform-socz80/deveth.h @@ -9,4 +9,6 @@ extern int eth_ioctl(uint8_t minor, uarg_t arg, char *data); extern void deveth_init(void); +extern void eth_poll(void); + #endif \ No newline at end of file diff --git a/Kernel/platform-socz80/ethernet.c b/Kernel/platform-socz80/ethernet.c index 48fe291a..58d89f84 100644 --- a/Kernel/platform-socz80/ethernet.c +++ b/Kernel/platform-socz80/ethernet.c @@ -25,6 +25,8 @@ __sfr __at 0x3e eth_spimode; static int eth_present; +static uint8_t ewait, enowait; + /* In bank 0 */ #define ERDPTL 0x00 #define ERDPTH 0x01 @@ -234,6 +236,10 @@ static void ethernet_reset(void) * Wait until free and then send a packet. We don't have an interrupt * mechanism for the SPI ethernet on the SocZ80 although we could add * one via a GPIO if it turns out useful + * + * Caution: We could have two threads of execution doing a read and + * a write. We won't pre-empt mid write but we may have a read poll + * running, so we must shut that off */ int eth_write(uint8_t minor, uint8_t rawflag, uint8_t flag) { @@ -248,6 +254,10 @@ int eth_write(uint8_t minor, uint8_t rawflag, uint8_t flag) udata.u_error = EFBIG; return -1; } + + /* Stop any read polling */ + enowait++; + eth_bank(0); while (eth_get(ECON1) & 0x8) { /* Not ready */ @@ -277,6 +287,10 @@ int eth_write(uint8_t minor, uint8_t rawflag, uint8_t flag) * Start transmit */ eth_cmd(BFS | ECON1, 0x08); + + /* Permit read polling to resume if active */ + enowait--; + return len; } @@ -315,11 +329,20 @@ int eth_read(uint8_t minor, uint8_t rawflag, uint8_t flag) /* Check carrier ?? */ + /* Wait for packet: bank must always be 1 before we set ewait */ eth_bank(1); - /* We have no IRQ so no sane blocking model .. yet */ - if (!eth_get(EPKTCNT)) /* Any packets waiting ? */ - return -EAGAIN; + /* We have no IRQ so its polled */ + while (eth_get(EPKTCNT) == 0) { + ewait = 1; + /* We will task switch to something else or idle and + in doing so enable interrupts for other tasks */ + if (psleep_flags(ð_present, flag)) + return -1; + } + /* Ensure ewait is clear before we re-enable interrupts */ + ewait = 0; + eth_bank(0); eth_cmd16(WCR | ERDPTL, eth_rxnext); eth_readpkt((uint8_t *)ð, 6); @@ -336,6 +359,16 @@ int eth_read(uint8_t minor, uint8_t rawflag, uint8_t flag) return r; } +void eth_poll(void) +{ + if (!ewait || enowait) + return; + /* if we are waiting for ethernet we are in bank 1, see + eth_read */ + if (eth_get(EPKTCNT)) + wakeup(ð_present); +} + int eth_open(uint8_t minor, uint16_t flag) { used(flag); diff --git a/Kernel/platform-socz80/main.c b/Kernel/platform-socz80/main.c index 74397883..2c3138a1 100644 --- a/Kernel/platform-socz80/main.c +++ b/Kernel/platform-socz80/main.c @@ -3,6 +3,7 @@ #include #include #include +#include uint16_t ramtop = PROGTOP; @@ -45,8 +46,10 @@ void platform_interrupt(void) if (st1 & 0x40) /* TX idle */ tty_outproc(2); } - if (ts & 1) + if (ts & 1) { + eth_poll(); timer_interrupt(); + } } void pagemap_init(void) -- 2.34.1