bsd_fdintr.s revision 1.26 1 1.26 jnemeth /* $NetBSD: bsd_fdintr.s,v 1.26 2007/06/21 09:45:54 jnemeth 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.21 pk ! tally interrupt (uvmexp.intrs++)
171 1.14 pk sethi %hi(_C_LABEL(uvmexp)+V_INTR), %l7
172 1.14 pk ld [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)], %l6
173 1.12 mrg inc %l6
174 1.14 pk st %l6, [%l7 + %lo(_C_LABEL(uvmexp)+V_INTR)]
175 1.1 pk
176 1.1 pk ! load fdc, if it's NULL there's nothing to do: schedule soft interrupt
177 1.14 pk sethi %hi(_C_LABEL(fdciop)), %l7
178 1.14 pk ld [%l7 + %lo(_C_LABEL(fdciop))], R_fdc
179 1.3 pk
180 1.21 pk ! tally interrupt (fdcio_intrcnt.ev_count++)
181 1.21 pk ldd [R_fdc + FDC_EVCNT], %l6
182 1.21 pk addcc %l7, 1, %l7
183 1.21 pk addx %l6, 0, %l6
184 1.21 pk std %l6, [R_fdc + FDC_EVCNT]
185 1.1 pk
186 1.20 thorpej /*
187 1.20 thorpej * load chips register addresses
188 1.20 thorpej * NOTE: we ignore the bus tag here and assume the bus handle
189 1.20 thorpej * is the virtual address of the chip's registers.
190 1.20 thorpej */
191 1.17 pk ld [R_fdc + FDC_REG_HANDLE], %l7 ! get chip registers bus handle
192 1.1 pk ld [R_fdc + FDC_REG_MSR], R_msr ! get chip MSR reg addr
193 1.17 pk add R_msr, %l7, R_msr
194 1.1 pk ld [R_fdc + FDC_REG_FIFO], R_fifo ! get chip FIFO reg addr
195 1.17 pk add R_fifo, %l7, R_fifo
196 1.1 pk !!ld [R_fdc + FDC_REG_DOR], R_dor ! get chip DOR reg addr
197 1.17 pk !!add R_dor, %l7, R_dor
198 1.1 pk
199 1.1 pk ! find out what we are supposed to do
200 1.18 pk ld [R_fdc + FDC_ITASK], %l7 ! get task from fdc
201 1.18 pk cmp %l7, FDC_ITASK_SENSEI
202 1.1 pk be sensei
203 1.18 pk !nop
204 1.18 pk cmp %l7, FDC_ITASK_RESULT
205 1.18 pk be resultphase
206 1.18 pk !nop
207 1.18 pk cmp %l7, FDC_ITASK_DMA
208 1.18 pk bne,a ssi ! a spurious interrupt
209 1.18 pk mov FDC_ISTATUS_SPURIOUS, %l7 ! set status and post sw intr
210 1.1 pk
211 1.1 pk ! pseudo DMA
212 1.1 pk ld [R_fdc + FDC_TC], R_tc ! residual count
213 1.1 pk ld [R_fdc + FDC_DATA], R_buf ! IO buffer
214 1.1 pk
215 1.1 pk ldub [R_msr], %l7 ! get MSR value
216 1.1 pk nextc:
217 1.1 pk btst NE7_RQM, %l7 ! room in fifo?
218 1.1 pk bnz,a 0f
219 1.26 jnemeth btst NE7_NDM, %l7 ! execution finished?
220 1.1 pk
221 1.1 pk ! we filled/emptied the FIFO; update fdc->sc_buf & fdc->sc_tc
222 1.1 pk st R_tc, [R_fdc + FDC_TC]
223 1.1 pk b x
224 1.1 pk st R_buf, [R_fdc + FDC_DATA]
225 1.1 pk
226 1.1 pk 0:
227 1.26 jnemeth bz resultphase
228 1.26 jnemeth
229 1.26 jnemeth tst R_tc
230 1.26 jnemeth bnz 0f
231 1.26 jnemeth nop
232 1.26 jnemeth
233 1.26 jnemeth !! panic("fdc: overrun")
234 1.26 jnemeth sethi %hi(.Lpanic_msg), %o0
235 1.26 jnemeth call _C_LABEL(panic)
236 1.26 jnemeth or %lo(.Lpanic_msg), %o0, %o0
237 1.26 jnemeth /* NOTREACHED */
238 1.26 jnemeth
239 1.26 jnemeth 0: btst NE7_DIO, %l7 ! IO direction
240 1.1 pk bz 1f
241 1.1 pk deccc R_tc
242 1.1 pk ldub [R_fifo], %l7 ! reading:
243 1.1 pk b 2f
244 1.1 pk stb %l7, [R_buf] ! *fdc->sc_bufp = *reg_fifo
245 1.1 pk
246 1.1 pk 1:
247 1.1 pk ldub [R_buf], %l7 ! writing:
248 1.1 pk stb %l7, [R_fifo] ! *reg_fifo = *fdc->sc_bufp
249 1.1 pk 2:
250 1.1 pk inc R_buf ! fdc->sc_bufp++
251 1.1 pk bne,a nextc ! if (--fdc->sc_tc) goto ...
252 1.1 pk ldub [R_msr], %l7 ! get MSR value
253 1.1 pk
254 1.9 pk ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate DONE
255 1.1 pk st R_tc, [R_fdc + FDC_TC]
256 1.1 pk st R_buf, [R_fdc + FDC_DATA]
257 1.1 pk
258 1.1 pk ! flip TC bit in auxreg
259 1.11 pk FD_ASSERT_TC
260 1.26 jnemeth nop; nop; nop ! XXX
261 1.11 pk FD_DEASSERT_TC
262 1.26 jnemeth b,a x
263 1.1 pk
264 1.1 pk
265 1.1 pk sensei:
266 1.1 pk ldub [R_msr], %l7
267 1.1 pk set POLL_TIMO, %l6
268 1.1 pk 1: deccc %l6 ! timeout?
269 1.18 pk be,a ssi ! if so, set status
270 1.18 pk mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt
271 1.1 pk and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7
272 1.1 pk cmp %l7, NE7_RQM
273 1.1 pk bne,a 1b ! loop till chip ready
274 1.1 pk ldub [R_msr], %l7
275 1.1 pk mov NE7CMD_SENSEI, %l7
276 1.1 pk stb %l7, [R_fifo]
277 1.1 pk
278 1.1 pk resultphase:
279 1.1 pk ! prepare for result phase
280 1.1 pk add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0]
281 1.1 pk mov -1, %l7
282 1.1 pk st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1;
283 1.1 pk
284 1.1 pk resultphase1:
285 1.1 pk clr R_stcnt
286 1.1 pk ldub [R_msr], %l7
287 1.1 pk set POLL_TIMO, %l6
288 1.1 pk 1: deccc %l6 ! timeout?
289 1.18 pk be,a ssi ! if so, set status
290 1.18 pk mov FDC_ISTATUS_ERROR, %l7 ! and post sw interrupt
291 1.1 pk and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7
292 1.1 pk cmp %l7, NE7_RQM
293 1.1 pk be 3f ! done
294 1.1 pk cmp %l7, (NE7_RQM | NE7_DIO | NE7_CB)
295 1.1 pk bne,a 1b ! loop till chip ready
296 1.1 pk ldub [R_msr], %l7
297 1.1 pk
298 1.1 pk cmp R_stcnt, FDC_NSTATUS ! status overrun?
299 1.1 pk bge 2f ! if so, load but dont store
300 1.1 pk ldub [R_fifo], %l7 ! load the status byte
301 1.1 pk stb %l7, [R_stat]
302 1.1 pk inc R_stat
303 1.1 pk inc R_stcnt
304 1.1 pk 2: b 1b
305 1.1 pk ldub [R_msr], %l7
306 1.1 pk
307 1.1 pk 3:
308 1.9 pk ! got status, update sc_nstat and mark istate DONE
309 1.1 pk st R_stcnt, [R_fdc + FDC_NSTAT]
310 1.18 pk mov FDC_ISTATUS_DONE, %l7
311 1.1 pk
312 1.1 pk ssi:
313 1.1 pk ! set software interrupt
314 1.18 pk ! enter here with status in %l7
315 1.24 wiz ! SMP: consider which CPU to ping?
316 1.18 pk st %l7, [R_fdc + FDC_ISTATUS]
317 1.9 pk FD_SET_SWINTR
318 1.1 pk
319 1.1 pk x:
320 1.1 pk /*
321 1.1 pk * Restore psr -- note: psr delay honored by pc restore loads.
322 1.1 pk */
323 1.1 pk set save_l, %l7
324 1.1 pk ldd [%l7], %l0
325 1.1 pk mov %l0, %psr
326 1.1 pk nop
327 1.1 pk ld [%l7 + 8], %l2
328 1.1 pk jmp %l1
329 1.1 pk rett %l2
330 1.26 jnemeth
331 1.26 jnemeth
332 1.26 jnemeth .Lpanic_msg:
333 1.26 jnemeth .asciz "fdc: overrun"
334 1.1 pk #endif
335