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