/* $NetBSD: bsd_fdintr.s,v 1.28 2010/12/20 00:25:43 matt Exp $ */ /* * Copyright (c) 1995 Paul Kranenburg * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Paul Kranenburg. * 4. 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. * */ #ifndef FDC_C_HANDLER #include "assym.h" #include #include #include #include #include #include #include #include #include #define FD_SET_SWINTR_4C \ sethi %hi(INTRREG_VA), %l5; \ ldub [%l5 + %lo(INTRREG_VA)], %l6; \ or %l6, IE_L4, %l6; \ stb %l6, [%l5 + %lo(INTRREG_VA)] ! raise(0,IPL_SOFTFDC) ! NOTE: CPU#0 #define FD_SET_SWINTR_4M \ sethi %hi(PINTR_SINTRLEV(IPL_SOFTFDC)), %l5; \ set ICR_PI_SET, %l6; \ st %l5, [%l6] /* set software interrupt */ #if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) #define FD_SET_SWINTR FD_SET_SWINTR_4C #elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) #define FD_SET_SWINTR FD_SET_SWINTR_4M #else #define FD_SET_SWINTR \ sethi %hi(_C_LABEL(cputyp)), %l5; \ ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ cmp %l5, CPU_SUN4M; \ be 8f; \ FD_SET_SWINTR_4C; \ ba,a 9f; \ 8: \ FD_SET_SWINTR_4M; \ 9: #endif ! flip TC bit in auxreg ! assumes %l6 remains unchanged between ASSERT and DEASSERT #define FD_ASSERT_TC_4C \ sethi %hi(AUXREG_VA), %l6; \ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ or %l7, AUXIO4C_MB1|AUXIO4C_FTC, %l7; \ stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; #define FD_DEASSERT_TC_4C \ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ andn %l7, AUXIO4C_FTC, %l7; \ or %l7, AUXIO4C_MB1, %l7; \ stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; ! flip TC bit in auxreg #define FD_ASSERT_TC_4M \ sethi %hi(AUXREG_VA), %l6; \ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ or %l7, AUXIO4M_MB1|AUXIO4M_FTC, %l7; \ stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; #define FD_DEASSERT_TC_4M /* * flip TC bit in auxreg * assumes %l5 remains unchanged between ASSERT and DEASSERT */ #if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) #define FD_ASSERT_TC FD_ASSERT_TC_4C #define FD_DEASSERT_TC FD_DEASSERT_TC_4C #elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) #define FD_ASSERT_TC FD_ASSERT_TC_4M #define FD_DEASSERT_TC FD_DEASSERT_TC_4M #else #define FD_ASSERT_TC \ sethi %hi(_C_LABEL(cputyp)), %l5; \ ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ cmp %l5, CPU_SUN4M; \ be 8f; \ nop; \ FD_ASSERT_TC_4C; \ ba,a 9f; \ 8: \ FD_ASSERT_TC_4M; \ 9: #define FD_DEASSERT_TC \ cmp %l5, CPU_SUN4M; \ be 8f; \ nop; \ FD_DEASSERT_TC_4C; \ ba,a 9f; \ 8: \ FD_DEASSERT_TC_4M; \ 9: #endif /* Timeout waiting for chip ready */ #define POLL_TIMO 100000 /* * register mnemonics. note overlapping assignments. */ #define R_fdc %l0 #define R_msr %l1 #define R_fifo %l2 #define R_buf %l3 #define R_tc %l4 #define R_stat %l3 #define R_nstat %l4 #define R_stcnt %l5 /* use %l6 and %l7 as short-term temporaries */ .seg "data" .align 8 /* A save haven for three precious registers */ save_l: .word 0 .word 0 .word 0 /* Pointer to a `struct fdcio', set in fd.c */ .global _C_LABEL(fdciop) _C_LABEL(fdciop): .word 0 .seg "text" .align 4 _ENTRY(_C_LABEL(fdchwintr)) set save_l, %l7 std %l0, [%l7] st %l2, [%l7 + 8] ! tally interrupt (curcpu()->cpu_data.cpu_nintr++) INCR64X(CPUINFO_VA+CPUINFO_NINTR, %l4, %l5, %l7) ! load fdc, if it's NULL there's nothing to do: schedule soft interrupt sethi %hi(_C_LABEL(fdciop)), %l7 ld [%l7 + %lo(_C_LABEL(fdciop))], R_fdc ! tally interrupt (fdcio_intrcnt.ev_count++) ldd [R_fdc + FDC_EVCNT], %l6 addcc %l7, 1, %l7 addx %l6, 0, %l6 std %l6, [R_fdc + FDC_EVCNT] /* * load chips register addresses * NOTE: we ignore the bus tag here and assume the bus handle * is the virtual address of the chip's registers. */ ld [R_fdc + FDC_REG_HANDLE], %l7 ! get chip registers bus handle ld [R_fdc + FDC_REG_MSR], R_msr ! get chip MSR reg addr add R_msr, %l7, R_msr ld [R_fdc + FDC_REG_FIFO], R_fifo ! get chip FIFO reg addr add R_fifo, %l7, R_fifo !!ld [R_fdc + FDC_REG_DOR], R_dor ! get chip DOR reg addr !!add R_dor, %l7, R_dor ! find out what we are supposed to do ld [R_fdc + FDC_ITASK], %l7 ! get task from fdc cmp %l7, FDC_ITASK_SENSEI be sensei !nop cmp %l7, FDC_ITASK_RESULT be resultphase !nop cmp %l7, FDC_ITASK_DMA bne,a ssi ! a spurious interrupt mov FDC_ISTATUS_SPURIOUS, %l7 ! set status and post sw intr ! pseudo DMA ld [R_fdc + FDC_TC], R_tc ! residual count ld [R_fdc + FDC_DATA], R_buf ! IO buffer ldub [R_msr], %l7 ! get MSR value nextc: btst NE7_RQM, %l7 ! room in fifo? bnz,a 0f btst NE7_NDM, %l7 ! execution finished? ! we filled/emptied the FIFO; update fdc->sc_buf & fdc->sc_tc st R_tc, [R_fdc + FDC_TC] b x st R_buf, [R_fdc + FDC_DATA] 0: bz resultphase tst R_tc bnz 0f nop !! panic("fdc: overrun") sethi %hi(.Lpanic_msg), %o0 call _C_LABEL(panic) or %lo(.Lpanic_msg), %o0, %o0 /* NOTREACHED */ 0: btst NE7_DIO, %l7 ! IO direction bz 1f deccc R_tc ldub [R_fifo], %l7 ! reading: b 2f stb %l7, [R_buf] ! *fdc->sc_bufp = *reg_fifo 1: ldub [R_buf], %l7 ! writing: stb %l7, [R_fifo] ! *reg_fifo = *fdc->sc_bufp 2: inc R_buf ! fdc->sc_bufp++ bne,a nextc ! if (--fdc->sc_tc) goto ... ldub [R_msr], %l7 ! get MSR value ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate DONE st R_tc, [R_fdc + FDC_TC] st R_buf, [R_fdc + FDC_DATA] ! flip TC bit in auxreg FD_ASSERT_TC nop; nop; nop ! XXX FD_DEASSERT_TC b,a x sensei: ldub [R_msr], %l7 set POLL_TIMO, %l6 1: deccc %l6 ! timeout? be,a ssi ! if so, set status mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 cmp %l7, NE7_RQM bne,a 1b ! loop till chip ready ldub [R_msr], %l7 mov NE7CMD_SENSEI, %l7 stb %l7, [R_fifo] resultphase: ! prepare for result phase add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0] mov -1, %l7 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1; resultphase1: clr R_stcnt ldub [R_msr], %l7 set POLL_TIMO, %l6 1: deccc %l6 ! timeout? be,a ssi ! if so, set status mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 cmp %l7, NE7_RQM be 3f ! done cmp %l7, (NE7_RQM | NE7_DIO | NE7_CB) bne,a 1b ! loop till chip ready ldub [R_msr], %l7 cmp R_stcnt, FDC_NSTATUS ! status overrun? bge 2f ! if so, load but dont store ldub [R_fifo], %l7 ! load the status byte stb %l7, [R_stat] inc R_stat inc R_stcnt 2: b 1b ldub [R_msr], %l7 3: ! got status, update sc_nstat and mark istate DONE st R_stcnt, [R_fdc + FDC_NSTAT] mov FDC_ISTATUS_DONE, %l7 ssi: ! set software interrupt ! enter here with status in %l7 ! SMP: consider which CPU to ping? st %l7, [R_fdc + FDC_ISTATUS] FD_SET_SWINTR x: /* * Restore psr -- note: psr delay honored by pc restore loads. */ set save_l, %l7 ldd [%l7], %l0 mov %l0, %psr nop ld [%l7 + 8], %l2 jmp %l1 rett %l2 .Lpanic_msg: .asciz "fdc: overrun" #endif