1/* $NetBSD: bsd_fdintr.s,v 1.19 2001/03/15 03:01:40 mrg Exp $ */ 2 3/* 4 * Copyright (c) 1995 Paul Kranenburg 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Paul Kranenburg. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 * 32 */ 33 34#ifndef FDC_C_HANDLER 35#include "assym.h" 36#include <machine/param.h> 37#include <machine/asm.h> 38#include <machine/psl.h> 39#include <sparc/sparc/intreg.h> 40#include <sparc/sparc/auxreg.h> 41#include <sparc/sparc/vaddrs.h> 42#include <sparc/dev/fdreg.h> 43#include <sparc/dev/fdvar.h> 44 45#define FD_SET_SWINTR_4C \ 46 sethi %hi(INTRREG_VA), %l5; \ 47 ldub [%l5 + %lo(INTRREG_VA)], %l6; \ 48 or %l6, IE_L4, %l6; \ 49 stb %l6, [%l5 + %lo(INTRREG_VA)] 50 51! raise(0,PIL_FDSOFT) ! NOTE: CPU#0 and PIL_FDSOFT=4 52#define FD_SET_SWINTR_4M \ 53 sethi %hi(PINTR_SINTRLEV(PIL_FDSOFT)), %l5; \ 54 set ICR_PI_SET, %l6; \ 55 st %l5, [%l6] 56 57/* set software interrupt */ 58#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) 59#define FD_SET_SWINTR FD_SET_SWINTR_4C 60#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) 61#define FD_SET_SWINTR FD_SET_SWINTR_4M 62#else 63#define FD_SET_SWINTR \ 64 sethi %hi(_C_LABEL(cputyp)), %l5; \ 65 ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ 66 cmp %l5, CPU_SUN4M; \ 67 be 8f; \ 68 FD_SET_SWINTR_4C; \ 69 ba,a 9f; \ 708: \ 71 FD_SET_SWINTR_4M; \ 729: 73#endif 74 75! flip TC bit in auxreg 76! assumes %l6 remains unchanged between ASSERT and DEASSERT 77#define FD_ASSERT_TC_4C \ 78 sethi %hi(AUXREG_VA), %l6; \ 79 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 80 or %l7, AUXIO4C_MB1|AUXIO4C_FTC, %l7; \ 81 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 82 83#define FD_DEASSERT_TC_4C \ 84 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 85 andn %l7, AUXIO4C_FTC, %l7; \ 86 or %l7, AUXIO4C_MB1, %l7; \ 87 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 88 89! flip TC bit in auxreg 90#define FD_ASSERT_TC_4M \ 91 sethi %hi(AUXREG_VA), %l6; \ 92 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 93 or %l7, AUXIO4M_MB1|AUXIO4M_FTC, %l7; \ 94 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 95 96#define FD_DEASSERT_TC_4M 97 98/* 99 * flip TC bit in auxreg 100 * assumes %l5 remains unchanged between ASSERT and DEASSERT 101 */ 102#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) 103#define FD_ASSERT_TC FD_ASSERT_TC_4C 104#define FD_DEASSERT_TC FD_DEASSERT_TC_4C 105#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) 106#define FD_ASSERT_TC FD_ASSERT_TC_4M 107#define FD_DEASSERT_TC FD_DEASSERT_TC_4M 108#else 109#define FD_ASSERT_TC \ 110 sethi %hi(_C_LABEL(cputyp)), %l5; \ 111 ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ 112 cmp %l5, CPU_SUN4M; \ 113 be 8f; \ 114 nop; \ 115 FD_ASSERT_TC_4C; \ 116 ba,a 9f; \ 1178: \ 118 FD_ASSERT_TC_4M; \ 1199: 120#define FD_DEASSERT_TC \ 121 cmp %l5, CPU_SUN4M; \ 122 be 8f; \ 123 nop; \ 124 FD_DEASSERT_TC_4C; \ 125 ba,a 9f; \ 1268: \ 127 FD_DEASSERT_TC_4M; \ 1289: 129#endif 130 131 132/* Timeout waiting for chip ready */ 133#define POLL_TIMO 100000 134 135/* 136 * register mnemonics. note overlapping assignments. 137 */ 138#define R_fdc %l0 139#define R_msr %l1 140#define R_fifo %l2 141#define R_buf %l3 142#define R_tc %l4 143#define R_stat %l3 144#define R_nstat %l4 145#define R_stcnt %l5 146/* use %l6 and %l7 as short term temporaries */ 147 148 149 .seg "data" 150 .align 8 151/* A save haven for three precious registers */ 152save_l: 153 .word 0 154 .word 0 155 .word 0 156/* Pointer to a `struct fdcio', set in fd.c */ 157 .global _C_LABEL(fdciop) 158_C_LABEL(fdciop): 159 .word 0 160 161 .seg "text" 162 .align 4 163 164/* XXXSMP: kernel lock perimeter? */ 165_ENTRY(_C_LABEL(fdchwintr)) 166 set save_l, %l7 167 std %l0, [%l7] 168 st %l2, [%l7 + 8] 169 170 ! tally interrupt 171 sethi %hi(_C_LABEL(uvmexp)+V_INTR), %l7 172 ld [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)], %l6 173 inc %l6 174 st %l6, [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)] 175 176 ! load fdc, if it's NULL there's nothing to do: schedule soft interrupt 177 sethi %hi(_C_LABEL(fdciop)), %l7 178 ld [%l7 + %lo(_C_LABEL(fdciop))], R_fdc 179 180 ! tally interrupt 181 ld [R_fdc + FDC_EVCNT], %l6 182 inc %l6 183 st %l6, [R_fdc + FDC_EVCNT] 184 185 ! load chips register addresses 186 ! NOTE: we ignore the bus tag here and assume the bus handle 187 ! is the virtual address of the chip's registers. 188 ld [R_fdc + FDC_REG_HANDLE], %l7 ! get chip registers bus handle 189 ld [R_fdc + FDC_REG_MSR], R_msr ! get chip MSR reg addr 190 add R_msr, %l7, R_msr 191 ld [R_fdc + FDC_REG_FIFO], R_fifo ! get chip FIFO reg addr 192 add R_fifo, %l7, R_fifo 193 !!ld [R_fdc + FDC_REG_DOR], R_dor ! get chip DOR reg addr 194 !!add R_dor, %l7, R_dor 195 196 ! find out what we are supposed to do 197 ld [R_fdc + FDC_ITASK], %l7 ! get task from fdc 198 cmp %l7, FDC_ITASK_SENSEI 199 be sensei 200 !nop 201 cmp %l7, FDC_ITASK_RESULT 202 be resultphase 203 !nop 204 cmp %l7, FDC_ITASK_DMA 205 bne,a ssi ! a spurious interrupt 206 mov FDC_ISTATUS_SPURIOUS, %l7 ! set status and post sw intr 207 208 ! pseudo DMA 209 ld [R_fdc + FDC_TC], R_tc ! residual count 210 ld [R_fdc + FDC_DATA], R_buf ! IO buffer 211 212 ldub [R_msr], %l7 ! get MSR value 213nextc: 214 btst NE7_RQM, %l7 ! room in fifo? 215 bnz,a 0f 216 btst NE7_NDM, %l7 ! overrun? 217 218 ! we filled/emptied the FIFO; update fdc->sc_buf & fdc->sc_tc 219 st R_tc, [R_fdc + FDC_TC] 220 b x 221 st R_buf, [R_fdc + FDC_DATA] 222 2230: 224 bz resultphase ! overrun/underrun 225 btst NE7_DIO, %l7 ! IO direction 226 bz 1f 227 deccc R_tc 228 ldub [R_fifo], %l7 ! reading: 229 b 2f 230 stb %l7, [R_buf] ! *fdc->sc_bufp = *reg_fifo 231 2321: 233 ldub [R_buf], %l7 ! writing: 234 stb %l7, [R_fifo] ! *reg_fifo = *fdc->sc_bufp 2352: 236 inc R_buf ! fdc->sc_bufp++ 237 bne,a nextc ! if (--fdc->sc_tc) goto ... 238 ldub [R_msr], %l7 ! get MSR value 239 240 ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate DONE 241 st R_tc, [R_fdc + FDC_TC] 242 st R_buf, [R_fdc + FDC_DATA] 243 244 ! flip TC bit in auxreg 245 FD_ASSERT_TC 246 247 ! we have some time to kill; anticipate on upcoming 248 ! result phase. 249 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0] 250 mov -1, %l7 251 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1; 252 253 FD_DEASSERT_TC 254 b,a resultphase1 255 256 257sensei: 258 ldub [R_msr], %l7 259 set POLL_TIMO, %l6 2601: deccc %l6 ! timeout? 261 be,a ssi ! if so, set status 262 mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt 263 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 264 cmp %l7, NE7_RQM 265 bne,a 1b ! loop till chip ready 266 ldub [R_msr], %l7 267 mov NE7CMD_SENSEI, %l7 268 stb %l7, [R_fifo] 269 270resultphase: 271 ! prepare for result phase 272 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0] 273 mov -1, %l7 274 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1; 275 276resultphase1: 277 clr R_stcnt 278 ldub [R_msr], %l7 279 set POLL_TIMO, %l6 2801: deccc %l6 ! timeout? 281 be,a ssi ! if so, set status 282 mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt 283 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 284 cmp %l7, NE7_RQM 285 be 3f ! done 286 cmp %l7, (NE7_RQM | NE7_DIO | NE7_CB) 287 bne,a 1b ! loop till chip ready 288 ldub [R_msr], %l7 289 290 cmp R_stcnt, FDC_NSTATUS ! status overrun? 291 bge 2f ! if so, load but dont store 292 ldub [R_fifo], %l7 ! load the status byte 293 stb %l7, [R_stat] 294 inc R_stat 295 inc R_stcnt 2962: b 1b 297 ldub [R_msr], %l7 298 2993: 300 ! got status, update sc_nstat and mark istate DONE 301 st R_stcnt, [R_fdc + FDC_NSTAT] 302 mov FDC_ISTATUS_DONE, %l7 303 304ssi: 305 ! set software interrupt 306 ! enter here with status in %l7 307 st %l7, [R_fdc + FDC_ISTATUS] 308 FD_SET_SWINTR 309 310x: 311 /* 312 * Restore psr -- note: psr delay honored by pc restore loads. 313 */ 314 set save_l, %l7 315 ldd [%l7], %l0 316 mov %l0, %psr 317 nop 318 ld [%l7 + 8], %l2 319 jmp %l1 320 rett %l2 321#endif 322