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