Re-organise eca(4)'s FIQ handlers. Now we have a single FIQ handler copied

to zero page, and it branches to either the rx or tx handler.  My intention
is that the tx handler should switch to the rx one the moment it finishes,
without needing a downgrade, which I hope will get rid of the start-of-frame
rx overruns I'm seeing.

While I'm here, move the constants describing the shape of the FIQ state
structures out of if_ecavar.h and into genassym.cf where they belong.
This commit is contained in:
bjh21 2001-09-20 21:54:11 +00:00
parent c4e2e1721f
commit b959cd4c1f
5 changed files with 83 additions and 76 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: genassym.cf,v 1.4 2001/09/10 23:41:48 bjh21 Exp $
# $NetBSD: genassym.cf,v 1.5 2001/09/20 21:54:11 bjh21 Exp $
#
# Copyright (c) 1999 Ben Harris
# All rights reserved.
@ -27,13 +27,19 @@
#
# This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines.
include "eca.h"
include <sys/param.h>
include <sys/mbuf.h>
include <sys/proc.h>
include <sys/user.h>
include <machine/pcb.h>
if NECA > 0
include <sys/mbuf.h>
include <arch/arm26/ioc/if_ecavar.h>
endif
define U_PCB offsetof(struct user, u_pcb)
define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
define P_ADDR offsetof(struct proc, p_addr)
@ -48,6 +54,16 @@ define IF_SIZE sizeof(struct irqframe)
define SIGF_SC offsetof(struct sigframe, sf_sc)
if NECA > 0
define M_NEXT offsetof(struct mbuf, m_next)
define M_DATA offsetof(struct mbuf, m_data)
define M_LEN offsetof(struct mbuf, m_len)
define EFS_FIQHANDLER offsetof(struct eca_fiqstate, efs_fiqhandler)
define EFS_RX_CURMBUF offsetof(struct eca_fiqstate, efs_rx_curmbuf)
define EFS_RX_FIQREGS offsetof(struct eca_fiqstate, efs_rx_fiqregs)
define EFS_RX_FLAGS offsetof(struct eca_fiqstate, efs_rx_flags)
define EFS_RX_MYADDR offsetof(struct eca_fiqstate, efs_rx_myaddr)
define EFS_TX_CURMBUF offsetof(struct eca_fiqstate, efs_tx_curmbuf)
endif

View File

@ -1,4 +1,4 @@
# $NetBSD: files.arm26,v 1.38 2001/09/10 23:41:49 bjh21 Exp $
# $NetBSD: files.arm26,v 1.39 2001/09/20 21:54:11 bjh21 Exp $
# Copyright (c) 1997, 1998, 2000 Ben Harris
# All rights reserved.
@ -113,7 +113,7 @@ attach wf at wfdc
# Econet module (Motorola 6854) (usually at bank 2 fiq 2)
device eca: fiq, eco, ifnet
attach eca at ioc
file arch/arm26/ioc/if_eca.c eca
file arch/arm26/ioc/if_eca.c eca needs-flag
file arch/arm26/ioc/if_eca_fiq.S eca
# On-board Rockwell 6551 serial (usually at bank 3 irq 10/1)

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_eca.c,v 1.4 2001/09/17 22:41:59 bjh21 Exp $ */
/* $NetBSD: if_eca.c,v 1.5 2001/09/20 21:54:11 bjh21 Exp $ */
/*-
* Copyright (c) 2001 Ben Harris
@ -29,7 +29,7 @@
#include <sys/param.h>
__KERNEL_RCSID(0, "$NetBSD: if_eca.c,v 1.4 2001/09/17 22:41:59 bjh21 Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_eca.c,v 1.5 2001/09/20 21:54:11 bjh21 Exp $");
#include <sys/device.h>
#include <sys/malloc.h>
@ -146,8 +146,7 @@ eca_init(struct ifnet *ifp)
return err;
/* Claim the FIQ early, in case we don't get it. */
if (fiq_claim(eca_fiqhandler_rx,
eca_efiqhandler_rx - eca_fiqhandler_rx))
if (fiq_claim(eca_fiqhandler, eca_efiqhandler - eca_fiqhandler))
return EBUSY;
if (sc->sc_rcvmbuf == NULL) {
@ -223,16 +222,16 @@ eca_txframe(struct ifnet *ifp, struct mbuf *m)
/* Start flag-filling while we work out what to do next. */
sc->sc_cr2 |= MC6854_CR2_RTS | MC6854_CR2_F_M_IDLE;
bus_space_write_1(iot, ioh, MC6854_CR2, sc->sc_cr2);
fiq_installhandler(eca_fiqhandler_tx,
eca_efiqhandler_tx - eca_fiqhandler_tx);
sc->sc_fiqstate.efs_fiqhandler = eca_fiqhandler_tx;
fiq_installhandler(eca_fiqhandler, eca_efiqhandler - eca_fiqhandler);
sc->sc_transmitting = 1;
sc->sc_txmbuf = m;
fr.r8_fiq = (register_t)sc->sc_ioh.a1;
fr.r9_fiq = (register_t)sc->sc_txmbuf->m_data;
fr.r10_fiq = (register_t)sc->sc_txmbuf->m_len;
fr.r11_fiq = (register_t)&sc->sc_txstate;
fr.r11_fiq = (register_t)&sc->sc_fiqstate;
fiq_setregs(&fr);
sc->sc_txstate.etx_curmbuf = sc->sc_txmbuf;
sc->sc_fiqstate.efs_tx_curmbuf = sc->sc_txmbuf;
fiq_downgrade_handler = eca_tx_downgrade;
/* Read and clear Tx status. */
bus_space_read_1(iot, ioh, MC6854_SR1);
@ -252,13 +251,10 @@ eca_tx_downgrade(void)
bus_space_handle_t ioh = sc->sc_ioh;
int sr1;
char buf[128];
#if 0
struct fiq_regs fr;
#endif
KASSERT(sc->sc_transmitting);
sc->sc_cr2 = 0;
if (__predict_true(sc->sc_txstate.etx_curmbuf == NULL)) {
if (__predict_true(sc->sc_fiqstate.efs_tx_curmbuf == NULL)) {
/* Entire frame got transmitted. */
} else {
sr1 = bus_space_read_1(iot, ioh, MC6854_SR1);
@ -347,9 +343,11 @@ eca_init_rx(struct eca_softc *sc)
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
struct fiq_regs fr;
int sr2;
fiq_installhandler(eca_fiqhandler_rx,
eca_efiqhandler_rx - eca_fiqhandler_rx);
sr2 = bus_space_read_1(iot, ioh, MC6854_SR2);
sc->sc_fiqstate.efs_fiqhandler = eca_fiqhandler_rx;
fiq_installhandler(eca_fiqhandler, eca_efiqhandler - eca_fiqhandler);
sc->sc_transmitting = 0;
sc->sc_cr1 = MC6854_CR1_RIE;
bus_space_write_1(iot, ioh, MC6854_CR1, sc->sc_cr1);
@ -357,13 +355,14 @@ eca_init_rx(struct eca_softc *sc)
fr.r8_fiq = (register_t)sc->sc_ioh.a1;
fr.r9_fiq = (register_t)sc->sc_rcvmbuf->m_data;
fr.r10_fiq = (register_t)ECO_ADDR_LEN;
fr.r11_fiq = (register_t)&sc->sc_rxstate;
sc->sc_rxstate.erx_curmbuf = sc->sc_rcvmbuf;
sc->sc_rxstate.erx_flags = 0;
sc->sc_rxstate.erx_myaddr = LLADDR(ifp->if_sadl)[0];
fr.r11_fiq = (register_t)&sc->sc_fiqstate;
sc->sc_fiqstate.efs_rx_curmbuf = sc->sc_rcvmbuf;
sc->sc_fiqstate.efs_rx_flags = 0;
sc->sc_fiqstate.efs_rx_myaddr = LLADDR(ifp->if_sadl)[0];
fiq_setregs(&fr);
fiq_downgrade_handler = eca_rx_downgrade;
eca_fiqowner = sc;
sr2 = bus_space_read_1(iot, ioh, MC6854_SR2);
ioc_fiq_setmask(IOC_FIQ_BIT(FIQ_EFIQ));
}
@ -425,6 +424,7 @@ eca_gotframe(void *arg)
if (__predict_false(sr2 & MC6854_SR2_OVRN)) {
log(LOG_ERR, "%s: Rx overrun\n", sc->sc_dev.dv_xname);
ifp->if_ierrors++;
/* Discard the rest of the frame. */
if (!sc->sc_transmitting)
bus_space_write_1(iot, ioh, MC6854_CR1,
@ -433,7 +433,7 @@ eca_gotframe(void *arg)
/* Frame Valid. */
fiq_getregs(&fr);
m = sc->sc_rcvmbuf;
mtail = sc->sc_rxstate.erx_curmbuf;
mtail = sc->sc_fiqstate.efs_rx_curmbuf;
/*
* Before we process this buffer, make sure we can get
* a new one.
@ -468,7 +468,7 @@ eca_gotframe(void *arg)
if (sr2 & MC6854_SR2_RX_IDLE)
eco_inputidle(ifp);
if (sc->sc_rxstate.erx_curmbuf == NULL) {
if (sc->sc_fiqstate.efs_rx_curmbuf == NULL) {
log(LOG_NOTICE, "%s: Oversized frame\n", sc->sc_dev.dv_xname);
ifp->if_ierrors++;
/* Discard the rest of the frame. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_eca_fiq.S,v 1.1 2001/09/10 23:41:49 bjh21 Exp $ */
/* $NetBSD: if_eca_fiq.S,v 1.2 2001/09/20 21:54:11 bjh21 Exp $ */
/*-
* Copyright (c) 2001 Ben Harris
@ -29,19 +29,24 @@
#include <machine/asm.h>
RCSID("$NetBSD: if_eca_fiq.S,v 1.1 2001/09/10 23:41:49 bjh21 Exp $")
RCSID("$NetBSD: if_eca_fiq.S,v 1.2 2001/09/20 21:54:11 bjh21 Exp $")
#include <dev/ic/mc6854reg.h>
#include <arch/arm26/ioc/if_ecavar.h>
#include "assym.h"
ENTRY_NP(eca_fiqhandler)
ldr pc, [r11, #EFS_FIQHANDLER]
.global eca_efiqhandler
_C_LABEL(eca_efiqhandler):
/*
* Econet Rx FIQ handler registers:
* R8: Address of 6854
* R9: Data buffer address
* R10: Space left in buffer
* R11: struct eca_rxstate pointer
* R11: struct eca_fiqstate pointer
* R12: Scratch
* R13: Scratch
*/
@ -63,31 +68,27 @@ Leca_rx_nodata:
teq r12, #0 /* No more status? */
subeqs pc, r14, #4 /* Return. */
tst r12, #MC6854_SR2_FV /* End of frame? */
ldrne r12, [r11, #ERX_FLAGS]
ldrne r12, [r11, #EFS_RX_FLAGS]
tstne r12, #ERXF_FLAGFILL /* Want flag fill? */
movne r12, #(MC6854_CR2_RTS | MC6854_CR2_F_M_IDLE)
strneb r12, [r8, #(MC6854_CR2 << 2)]
Leca_rx_downgrade:
ldr pc, Leca_rx_fiq_downgrade
Leca_rx_fiq_downgrade:
.word fiq_downgrade
b fiq_downgrade
Leca_rx_counter:
/* If we've already got the header, this indicates end-of-buffer. */
ldr r12, [r11, #ERX_FLAGS]
ldr r12, [r11, #EFS_RX_FLAGS]
tst r12, #ERXF_GOTHDR
bne Leca_rx_full
ldrb r12, [r9, #-2]
ldrb r13, [r11, #ERX_MYADDR]
ldrb r13, [r11, #EFS_RX_MYADDR]
teq r12, r13 /* Our host */
ldreqb r12, [r9, #-1]
teqeq r12, #0 /* Local network? */
ldr r12, [r11, #ERX_FLAGS]
ldr r12, [r11, #EFS_RX_FLAGS]
orrne r12, r12, #ERXF_GOTHDR
orreq r12, r12, #(ERXF_GOTHDR | ERXF_FLAGFILL)
str r12, [r11, #ERX_FLAGS]
ldr r12, [r11, #ERX_CURMBUF]
str r12, [r11, #EFS_RX_FLAGS]
ldr r12, [r11, #EFS_RX_CURMBUF]
ldr r10, [r12, #M_LEN]
ldr r12, [r12, #M_DATA]
sub r12, r9, r12 /* Amount got already */
@ -96,24 +97,21 @@ Leca_rx_counter:
Leca_rx_full:
/* Rx buffer full. See if there's another mbuf in the chain. */
ldr r12, [r11, #ERX_CURMBUF]
ldr r12, [r11, #EFS_RX_CURMBUF]
ldr r12, [r12, #M_NEXT]
str r12, [r11, #ERX_CURMBUF]
str r12, [r11, #EFS_RX_CURMBUF]
teq r12, #0
beq Leca_rx_downgrade
beq fiq_downgrade
ldr r9, [r12, #M_DATA]
ldr r10, [r12, #M_LEN]
subs pc, r14, #4
.global eca_efiqhandler_rx
_C_LABEL(eca_efiqhandler_rx):
/*
* Econet Tx FIQ handler registers:
* R8: Address of 6854
* R9: Data buffer address
* R10: Data left in buffer
* R11: struct eca_txstate pointer
* R11: struct eca_fiqstate pointer
* R12: Scratch
* R13: Scratch
*/
@ -132,24 +130,17 @@ Leca_tx_loop:
Leca_tx_nospace:
tst r12, #MC6854_SR1_IRQ /* No more status? */
subeqs pc, r14, #4 /* Return. */
ldr pc, Leca_tx_fiq_downgrade
b fiq_downgrade
Leca_tx_nodata:
/* We get here when the current data block is empty. */
ldr r12, [r11, #ETX_CURMBUF]
ldr r12, [r11, #EFS_TX_CURMBUF]
ldr r12, [r12, #M_NEXT]
str r12, [r11, #ETX_CURMBUF]
str r12, [r11, #EFS_TX_CURMBUF]
teq r12, #0 /* Another mbuf? */
moveq r12, #(MC6854_CR2_TX_LAST) /* If not, finish frame... */
streqb r12, [r8, #(MC6854_CR2 << 2)]
ldreq pc, Leca_tx_fiq_downgrade /* ... and report back. */
beq fiq_downgrade /* ... and report back. */
ldr r9, [r12, #M_DATA] /* Line up next mbuf. */
ldr r10, [r12, #M_LEN]
subs pc, r14, #4
Leca_tx_fiq_downgrade:
.word fiq_downgrade
.global eca_efiqhandler_tx
_C_LABEL(eca_efiqhandler_tx):

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ecavar.h,v 1.2 2001/09/15 17:27:25 bjh21 Exp $ */
/* $NetBSD: if_ecavar.h,v 1.3 2001/09/20 21:54:11 bjh21 Exp $ */
/*-
* Copyright (c) 2001 Ben Harris
@ -31,17 +31,22 @@
#define _ECAVAR_H_
#ifndef _LOCORE
#include <sys/device.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_eco.h>
struct eca_rxstate {
struct mbuf *erx_curmbuf;
u_int32_t erx_flags;
u_int8_t erx_myaddr;
};
#include <machine/bus.h>
#include <machine/fiq.h>
struct eca_txstate {
struct mbuf *etx_curmbuf;
struct eca_fiqstate {
void *efs_fiqhandler;
struct mbuf *efs_rx_curmbuf;
struct fiq_regs efs_rx_fiqregs;
u_int32_t efs_rx_flags;
u_int8_t efs_rx_myaddr;
struct mbuf *efs_tx_curmbuf;
};
struct eca_softc {
@ -53,27 +58,22 @@ struct eca_softc {
u_int8_t sc_cr4;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
struct mbuf *sc_rcvmbuf;
void *sc_rx_soft;
struct eca_rxstate sc_rxstate;
u_int8_t sc_sr2;
struct eca_fiqstate sc_fiqstate;
struct mbuf *sc_rcvmbuf;
struct mbuf *sc_txmbuf;
u_int8_t sc_sr2;
void *sc_tx_soft;
struct eca_txstate sc_txstate;
int sc_transmitting;
};
extern char eca_fiqhandler_rx[], eca_efiqhandler_rx[];
extern char eca_fiqhandler_tx[], eca_efiqhandler_tx[];
extern char eca_fiqhandler[], eca_efiqhandler[];
extern char eca_fiqhandler_rx[], eca_fiqhandler_tx[];
#endif
/* Sync with rxstate above */
#define ERX_CURMBUF 0
#define ERX_FLAGS 4
/* Flags for efs_rx_flags. */
#define ERXF_GOTHDR 0x01
#define ERXF_FLAGFILL 0x02
#define ERX_MYADDR 8
/* Sync with txstate above */
#define ETX_CURMBUF 0
#endif