bsd_fdintr.s revision 1.6 1 /* $NetBSD: bsd_fdintr.s,v 1.6 1996/02/02 02:37:22 mycroft 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 #ifndef _LOCORE
36 #define _LOCORE
37 #endif
38 #include "assym.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 /* XXX this goes in a header file -- currently, it's hidden in locore.s */
45 #define INTREG_ADDR 0xf8002000
46
47 /* Timeout waiting for chip ready */
48 #define POLL_TIMO 100000
49
50 /*
51 * register mnemonics. note overlapping assignments.
52 */
53 #define R_fdc %l0
54 #define R_msr %l1
55 #define R_fifo %l2
56 #define R_buf %l3
57 #define R_tc %l4
58 #define R_stat %l3
59 #define R_nstat %l4
60 #define R_stcnt %l5
61 /* use %l6 and %l7 as short term temporaries */
62
63
64 .seg "data"
65 .align 8
66 .global _fdciop
67 /* A save haven for three precious registers */
68 save_l:
69 .word 0
70 .word 0
71 .word 0
72 /* Pointer to a `struct fdcio', set in fd.c */
73 _fdciop:
74 .word 0
75
76 .seg "text"
77 .align 4
78 .global _fdchwintr
79
80 _fdchwintr:
81 set save_l, %l7
82 std %l0, [%l7]
83 st %l2, [%l7 + 8]
84
85 ! tally interrupt
86 sethi %hi(_cnt+V_INTR), %l7
87 ld [%l7 + %lo(_cnt+V_INTR)], %l6
88 inc %l6
89 st %l6, [%l7 + %lo(_cnt+V_INTR)]
90
91 ! load fdc, if it's NULL there's nothing to do: schedule soft interrupt
92 sethi %hi(_fdciop), %l7
93 ld [%l7 + %lo(_fdciop)], R_fdc
94
95 ! tally interrupt
96 ld [R_fdc + FDC_EVCNT], %l6
97 inc %l6
98 st %l6, [R_fdc + FDC_EVCNT]
99
100 ! load chips register addresses
101 ld [R_fdc + FDC_REG_MSR], R_msr ! get chip MSR reg addr
102 ld [R_fdc + FDC_REG_FIFO], R_fifo ! get chip FIFO reg addr
103 !!ld [R_fdc + FDC_REG_DOR], R_dor ! get chip DOR reg addr
104
105 ! find out what we are supposed to do
106 ld [R_fdc + FDC_ISTATE], %l7 ! examine flags
107 cmp %l7, ISTATE_SENSEI
108 be sensei
109 nop
110 cmp %l7, ISTATE_DMA
111 bne spurious
112 nop
113
114 ! pseudo DMA
115 ld [R_fdc + FDC_TC], R_tc ! residual count
116 ld [R_fdc + FDC_DATA], R_buf ! IO buffer
117
118 ldub [R_msr], %l7 ! get MSR value
119 nextc:
120 btst NE7_RQM, %l7 ! room in fifo?
121 bnz,a 0f
122 btst NE7_NDM, %l7 ! overrun?
123
124 ! we filled/emptied the FIFO; update fdc->sc_buf & fdc->sc_tc
125 st R_tc, [R_fdc + FDC_TC]
126 b x
127 st R_buf, [R_fdc + FDC_DATA]
128
129 0:
130 bz resultphase ! overrun/underrun
131 btst NE7_DIO, %l7 ! IO direction
132 bz 1f
133 deccc R_tc
134 ldub [R_fifo], %l7 ! reading:
135 b 2f
136 stb %l7, [R_buf] ! *fdc->sc_bufp = *reg_fifo
137
138 1:
139 ldub [R_buf], %l7 ! writing:
140 stb %l7, [R_fifo] ! *reg_fifo = *fdc->sc_bufp
141 2:
142 inc R_buf ! fdc->sc_bufp++
143 bne,a nextc ! if (--fdc->sc_tc) goto ...
144 ldub [R_msr], %l7 ! get MSR value
145
146 ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate IDLE
147 st R_tc, [R_fdc + FDC_TC]
148 st R_buf, [R_fdc + FDC_DATA]
149
150 ! flip TC bit in auxreg
151 sethi %hi(_auxio_reg), %l6
152 ld [%l6 + %lo(_auxio_reg)], %l6
153 ldub [%l6], %l7
154 or %l7, AUXIO_MB1|AUXIO_FTC, %l7
155 stb %l7, [%l6]
156
157 ! we have some time to kill; anticipate on upcoming
158 ! result phase.
159 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0]
160 mov -1, %l7
161 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1;
162
163 ldub [%l6], %l7
164 andn %l7, AUXIO_FTC, %l7
165 or %l7, AUXIO_MB1, %l7
166 stb %l7, [%l6]
167 b resultphase1
168 nop
169
170 spurious:
171 mov ISTATE_SPURIOUS, %l7
172 st %l7, [R_fdc + FDC_ISTATE]
173 b,a ssi
174
175 sensei:
176 ldub [R_msr], %l7
177 set POLL_TIMO, %l6
178 1: deccc %l6 ! timeout?
179 be ssi
180 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7
181 cmp %l7, NE7_RQM
182 bne,a 1b ! loop till chip ready
183 ldub [R_msr], %l7
184 mov NE7CMD_SENSEI, %l7
185 stb %l7, [R_fifo]
186
187 resultphase:
188 ! prepare for result phase
189 add R_fdc, FDC_STATUS, R_stat ! &fdc->sc_status[0]
190 mov -1, %l7
191 st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1;
192
193 resultphase1:
194 clr R_stcnt
195 ldub [R_msr], %l7
196 set POLL_TIMO, %l6
197 1: deccc %l6 ! timeout?
198 be ssi
199 and %l7, (NE7_RQM | NE7_DIO | NE7_CB), %l7
200 cmp %l7, NE7_RQM
201 be 3f ! done
202 cmp %l7, (NE7_RQM | NE7_DIO | NE7_CB)
203 bne,a 1b ! loop till chip ready
204 ldub [R_msr], %l7
205
206 cmp R_stcnt, FDC_NSTATUS ! status overrun?
207 bge 2f ! if so, load but dont store
208 ldub [R_fifo], %l7 ! load the status byte
209 stb %l7, [R_stat]
210 inc R_stat
211 inc R_stcnt
212 2: b 1b
213 ldub [R_msr], %l7
214
215 3:
216 ! got status, update sc_nstat and mark istate IDLE
217 st R_stcnt, [R_fdc + FDC_NSTAT]
218 mov ISTATE_IDLE, %l7
219 st %l7, [R_fdc + FDC_ISTATE]
220
221 ssi:
222 ! set software interrupt
223 sethi %hi(INTREG_ADDR), %l7
224 ldsb [%l7 + %lo(INTREG_ADDR)], %l6
225 or %l6, IE_L4, %l6
226 stb %l6, [%l7 + %lo(INTREG_ADDR)]
227
228 x:
229 /*
230 * Restore psr -- note: psr delay honored by pc restore loads.
231 */
232 set save_l, %l7
233 ldd [%l7], %l0
234 mov %l0, %psr
235 nop
236 ld [%l7 + 8], %l2
237 jmp %l1
238 rett %l2
239 #endif
240