1/* $NetBSD: bsd_fdintr.s,v 1.22 2002/12/06 15:37:55 pk 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/intr.h> 39#include <machine/psl.h> 40#include <sparc/sparc/intreg.h> 41#include <sparc/sparc/auxreg.h> 42#include <sparc/sparc/vaddrs.h> 43#include <sparc/dev/fdreg.h> 44#include <sparc/dev/fdvar.h> 45 46#define FD_SET_SWINTR_4C \ 47 sethi %hi(INTRREG_VA), %l5; \ 48 ldub [%l5 + %lo(INTRREG_VA)], %l6; \ 49 or %l6, IE_L4, %l6; \ 50 stb %l6, [%l5 + %lo(INTRREG_VA)] 51 52! raise(0,IPL_SOFTFDC) ! NOTE: CPU#0 53#define FD_SET_SWINTR_4M \ 54 sethi %hi(PINTR_SINTRLEV(IPL_SOFTFDC)), %l5; \ 55 set ICR_PI_SET, %l6; \ 56 st %l5, [%l6] 57 58/* set software interrupt */ 59#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) 60#define FD_SET_SWINTR FD_SET_SWINTR_4C 61#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) 62#define FD_SET_SWINTR FD_SET_SWINTR_4M 63#else 64#define FD_SET_SWINTR \ 65 sethi %hi(_C_LABEL(cputyp)), %l5; \ 66 ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ 67 cmp %l5, CPU_SUN4M; \ 68 be 8f; \ 69 FD_SET_SWINTR_4C; \ 70 ba,a 9f; \ 718: \ 72 FD_SET_SWINTR_4M; \ 739: 74#endif 75 76! flip TC bit in auxreg 77! assumes %l6 remains unchanged between ASSERT and DEASSERT 78#define FD_ASSERT_TC_4C \ 79 sethi %hi(AUXREG_VA), %l6; \ 80 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 81 or %l7, AUXIO4C_MB1|AUXIO4C_FTC, %l7; \ 82 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 83 84#define FD_DEASSERT_TC_4C \ 85 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 86 andn %l7, AUXIO4C_FTC, %l7; \ 87 or %l7, AUXIO4C_MB1, %l7; \ 88 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 89 90! flip TC bit in auxreg 91#define FD_ASSERT_TC_4M \ 92 sethi %hi(AUXREG_VA), %l6; \ 93 ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \ 94 or %l7, AUXIO4M_MB1|AUXIO4M_FTC, %l7; \ 95 stb %l7, [%l6 + %lo(AUXREG_VA) + 3]; 96 97#define FD_DEASSERT_TC_4M 98 99/* 100 * flip TC bit in auxreg 101 * assumes %l5 remains unchanged between ASSERT and DEASSERT 102 */ 103#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M) 104#define FD_ASSERT_TC FD_ASSERT_TC_4C 105#define FD_DEASSERT_TC FD_DEASSERT_TC_4C 106#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M) 107#define FD_ASSERT_TC FD_ASSERT_TC_4M 108#define FD_DEASSERT_TC FD_DEASSERT_TC_4M 109#else 110#define FD_ASSERT_TC \ 111 sethi %hi(_C_LABEL(cputyp)), %l5; \ 112 ld [%l5 + %lo(_C_LABEL(cputyp))], %l5; \ 113 cmp %l5, CPU_SUN4M; \ 114 be 8f; \ 115 nop; \ 116 FD_ASSERT_TC_4C; \ 117 ba,a 9f; \ 1188: \ 119 FD_ASSERT_TC_4M; \ 1209: 121#define FD_DEASSERT_TC \ 122 cmp %l5, CPU_SUN4M; \ 123 be 8f; \ 124 nop; \ 125 FD_DEASSERT_TC_4C; \ 126 ba,a 9f; \ 1278: \ 128 FD_DEASSERT_TC_4M; \ 1299: 130#endif 131 132 133/* Timeout waiting for chip ready */ 134#define POLL_TIMO 100000 135 136/* 137 * register mnemonics. note overlapping assignments. 138 */ 139#define R_fdc %l0 140#define R_msr %l1 141#define R_fifo %l2 142#define R_buf %l3 143#define R_tc %l4 144#define R_stat %l3 145#define R_nstat %l4 146#define R_stcnt %l5 147/* use %l6 and %l7 as short-term temporaries */ 148 149 150 .seg "data" 151 .align 8 152/* A save haven for three precious registers */ 153save_l: 154 .word 0 155 .word 0 156 .word 0 157/* Pointer to a `struct fdcio', set in fd.c */ 158 .global _C_LABEL(fdciop) 159_C_LABEL(fdciop): 160 .word 0 161 162 .seg "text" 163 .align 4 164 165/* XXXSMP: kernel lock perimeter? */ 166_ENTRY(_C_LABEL(fdchwintr)) 167 set save_l, %l7 168 std %l0, [%l7] 169 st %l2, [%l7 + 8] 170 171 ! tally interrupt (uvmexp.intrs++) 172 sethi %hi(_C_LABEL(uvmexp)+V_INTR), %l7 173 ld [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)], %l6 174 inc %l6 175 st %l6, [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)] 176 177 ! load fdc, if it's NULL there's nothing to do: schedule soft interrupt 178 sethi %hi(_C_LABEL(fdciop)), %l7 179 ld [%l7 + %lo(_C_LABEL(fdciop))], R_fdc 180 181 ! tally interrupt (fdcio_intrcnt.ev_count++) 182 ldd [R_fdc + FDC_EVCNT], %l6 183 addcc %l7, 1, %l7 184 addx %l6, 0, %l6 185 std %l6, [R_fdc + FDC_EVCNT] 186 187 /* 188 * load chips register addresses 189 * NOTE: we ignore the bus tag here and assume the bus handle 190 * is the virtual address of the chip's registers. 191 */ 192 ld [R_fdc + FDC_REG_HANDLE], %l7 ! get chip registers bus handle 193 ld [R_fdc + FDC_REG_MSR], R_msr ! get chip MSR reg addr 194 add R_msr, %l7, R_msr 195 ld [R_fdc + FDC_REG_FIFO], R_fifo ! get chip FIFO reg addr 196 add R_fifo, %l7, R_fifo 197 !!ld [R_fdc + FDC_REG_DOR], R_dor ! get chip DOR reg addr 198 !!add R_dor, %l7, R_dor 199 200 ! find out what we are supposed to do 201 ld [R_fdc + FDC_ITASK], %l7 ! get task from fdc 202 cmp %l7, FDC_ITASK_SENSEI 203 be sensei 204 !nop 205 cmp %l7, FDC_ITASK_RESULT 206 be resultphase 207 !nop 208 cmp %l7, FDC_ITASK_DMA 209 bne,a ssi ! a spurious interrupt 210 mov FDC_ISTATUS_SPURIOUS, %l7 ! set status and post sw intr 211 212 ! pseudo DMA 213 ld [R_fdc + FDC_TC], R_tc ! residual count 214 ld [R_fdc + FDC_DATA], R_buf ! IO buffer 215 216 ldub [R_msr], %l7 ! get MSR value 217nextc: 218 btst NE7_RQM, %l7 ! room in fifo? 219 bnz,a 0f 220 btst NE7_NDM, %l7 ! overrun? 221 222 ! we filled/emptied the FIFO; update fdc->sc_buf & fdc->sc_tc 223 st R_tc, [R_fdc + FDC_TC] 224 b x 225 st R_buf, [R_fdc + FDC_DATA] 226 2270: 228 bz resultphase ! overrun/underrun 229 btst NE7_DIO, %l7 ! IO direction 230 bz 1f 231 deccc R_tc 232 ldub [R_fifo], %l7 ! reading: 233 b 2f 234 stb %l7, [R_buf] ! *fdc->sc_bufp = *reg_fifo 235 2361: 237 ldub [R_buf], %l7 ! writing: 238 stb %l7, [R_fifo] ! *reg_fifo = *fdc->sc_bufp 2392: 240 inc R_buf ! fdc->sc_bufp++ 241 bne,a nextc ! if (--fdc->sc_tc) goto ... 242 ldub [R_msr], %l7 ! get MSR value 243 244 ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate DONE 245 st R_tc, [R_fdc + FDC_TC] 246 st R_buf, [R_fdc + FDC_DATA] 247 248 ! flip TC bit in auxreg 249 FD_ASSERT_TC 250 251 ! we have some time to kill; anticipate on upcoming 252 ! result phase. 253 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0] 254 mov -1, %l7 255 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1; 256 257 FD_DEASSERT_TC 258 b,a resultphase1 259 260 261sensei: 262 ldub [R_msr], %l7 263 set POLL_TIMO, %l6 2641: deccc %l6 ! timeout? 265 be,a ssi ! if so, set status 266 mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt 267 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 268 cmp %l7, NE7_RQM 269 bne,a 1b ! loop till chip ready 270 ldub [R_msr], %l7 271 mov NE7CMD_SENSEI, %l7 272 stb %l7, [R_fifo] 273 274resultphase: 275 ! prepare for result phase 276 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0] 277 mov -1, %l7 278 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1; 279 280resultphase1: 281 clr R_stcnt 282 ldub [R_msr], %l7 283 set POLL_TIMO, %l6 2841: deccc %l6 ! timeout? 285 be,a ssi ! if so, set status 286 mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt 287 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7 288 cmp %l7, NE7_RQM 289 be 3f ! done 290 cmp %l7, (NE7_RQM | NE7_DIO | NE7_CB) 291 bne,a 1b ! loop till chip ready 292 ldub [R_msr], %l7 293 294 cmp R_stcnt, FDC_NSTATUS ! status overrun? 295 bge 2f ! if so, load but dont store 296 ldub [R_fifo], %l7 ! load the status byte 297 stb %l7, [R_stat] 298 inc R_stat 299 inc R_stcnt 3002: b 1b 301 ldub [R_msr], %l7 302 3033: 304 ! got status, update sc_nstat and mark istate DONE 305 st R_stcnt, [R_fdc + FDC_NSTAT] 306 mov FDC_ISTATUS_DONE, %l7 307 308ssi: 309 ! set software interrupt 310 ! enter here with status in %l7 311 st %l7, [R_fdc + FDC_ISTATUS] 312 FD_SET_SWINTR 313 314x: 315 /* 316 * Restore psr -- note: psr delay honored by pc restore loads. 317 */ 318 set save_l, %l7 319 ldd [%l7], %l0 320 mov %l0, %psr 321 nop 322 ld [%l7 + 8], %l2 323 jmp %l1 324 rett %l2 325#endif 326