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