/* $NetBSD: if_eca_fiq.S,v 1.2 2002/03/24 23:17:00 bjh21 Exp $ */ /*- * Copyright (c) 2001 Ben Harris * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <machine/asm.h> RCSID("$NetBSD: if_eca_fiq.S,v 1.2 2002/03/24 23:17:00 bjh21 Exp $") #include <dev/ic/mc6854reg.h> #include <arch/acorn26/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_fiqstate pointer * R12: Scratch * R13: Scratch */ ENTRY(eca_fiqhandler_rx) /* If there's something in the Rx FIFO, read it now. */ ldrb r12, [r8, #(MC6854_SR2 << 2)] tst r12, #MC6854_SR2_OVRN bne Leca_rx_nodata tst r12, #MC6854_SR2_RDA beq Leca_rx_nodata Leca_rx_loop: ldrb r12, [r8, #(MC6854_RXFIFO << 2)] strb r12, [r9], #1 subs r10, r10, #1 beq Leca_rx_counter /* Rx buffer full */ ldrb r12, [r8, #(MC6854_SR2 << 2)] tst r12, #MC6854_SR2_RDA /* More data? */ bne Leca_rx_loop 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, #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)] b fiq_downgrade Leca_rx_counter: /* If we've already got the header, this indicates end-of-buffer. */ ldr r12, [r11, #EFS_RX_FLAGS] tst r12, #ERXF_GOTHDR bne Leca_rx_full ldrb r12, [r9, #-2] ldrb r13, [r11, #EFS_RX_MYADDR] teq r12, r13 /* Our host */ ldreqb r12, [r9, #-1] teqeq r12, #0 /* Local network? */ ldr r12, [r11, #EFS_RX_FLAGS] orrne r12, r12, #ERXF_GOTHDR orreq r12, r12, #(ERXF_GOTHDR | ERXF_FLAGFILL) 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 */ sub r10, r10, r12 subs pc, r14, #4 Leca_rx_full: /* Rx buffer full. See if there's another mbuf in the chain. */ ldr r12, [r11, #EFS_RX_CURMBUF] ldr r12, [r12, #M_NEXT] str r12, [r11, #EFS_RX_CURMBUF] teq r12, #0 beq fiq_downgrade ldr r9, [r12, #M_DATA] ldr r10, [r12, #M_LEN] subs pc, r14, #4 /* * Econet Tx FIQ handler registers: * R8: Address of 6854 * R9: Data buffer address * R10: Data left in buffer * R11: struct eca_fiqstate pointer * R12: Scratch * R13: Scratch */ ENTRY(eca_fiqhandler_tx) ldrb r12, [r8, #(MC6854_SR1 << 2)] tst r12, #MC6854_SR1_TDRA beq Leca_tx_nospace Leca_tx_loop: ldrb r12, [r9], #1 strb r12, [r8, #(MC6854_TXFIFOFC << 2)] subs r10, r10, #1 beq Leca_tx_nodata ldrb r12, [r8, #(MC6854_SR1 << 2)] tst r12, #MC6854_SR1_TDRA bne Leca_tx_loop Leca_tx_nospace: tst r12, #MC6854_SR1_IRQ /* No more status? */ subeqs pc, r14, #4 /* Return. */ b fiq_downgrade Leca_tx_nodata: /* We get here when the current data block is empty. */ ldr r12, [r11, #EFS_TX_CURMBUF] ldr r12, [r12, #M_NEXT] str r12, [r11, #EFS_TX_CURMBUF] teq r12, #0 /* Another mbuf? */ beq Leca_tx_endofframe ldr r9, [r12, #M_DATA] /* Line up next mbuf. */ ldr r10, [r12, #M_LEN] subs pc, r14, #4 Leca_tx_endofframe: mov r12, #(MC6854_CR2_TX_LAST) /* If not, finish frame... */ strb r12, [r8, #(MC6854_CR2 << 2)] /* Code equivalent to parts of eca_init_rx_hard() */ adr r12, _C_LABEL(eca_fiqhandler_rx) str r12, [r11, #(EFS_FIQHANDLER)] mov r12, #(MC6854_CR1_RIE) strb r12, [r8, #(MC6854_CR1 << 2)] add r12, r11, #(EFS_RX_FIQREGS) ldmia r12, {r8-r11} /* End code equivalent to parts of eca_init_rx_hard() */ b fiq_downgrade_dont_disable /* ... and report back. */