1 /* $NecBSD: bshw_pdma.c,v 1.4 1997/10/31 17:43:39 honda Exp $ */
2 /* $NetBSD$ */
3 /*
4 * [NetBSD for NEC PC98 series]
5 * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31 /*
32 * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
33 */
34
35 #define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */
36
37 static BS_INLINE void bshw_lc_smit_start __P((struct bs_softc *, int, u_int));
38 static int bshw_lc_smit_fstat __P((struct bs_softc *, int, int));
39 static BS_INLINE void bshw_lc_smit_stop __P((struct bs_softc *));
40
41 /*********************************************************
42 * SM FIFO (GENERIC)
43 *********************************************************/
44 void
45 bshw_smitabort(bsc)
46 struct bs_softc *bsc;
47 {
48 if (bsc->sc_hw->hw_flags & BSHW_SMFIFO)
49 bshw_lc_smit_stop(bsc);
50
51 bshw_set_count(bsc, 0);
52 bsc->sc_flags &= ~BSSMITSTART;
53 }
54
55 void
56 bs_smit_xfer_end(ti)
57 struct targ_info *ti;
58 {
59 struct bs_softc *bsc = ti->ti_bsc;
60 struct sc_p *sp = &bsc->sc_p;
61 u_int count;
62 u_char *s;
63
64 bshw_lc_smit_stop(bsc);
65 bsc->sc_flags &= ~BSSMITSTART;
66
67 if (ti->ti_phase == DATAPHASE)
68 {
69 count = bshw_get_count(bsc);
70 if (count < (u_int) sp->datalen)
71 {
72 sp->data += (sp->datalen - count);
73 sp->datalen = count;
74 /* XXX:
75 * strict double checks!
76 * target => wd33c93c transfer counts
77 * wd33c93c => memory transfer counts
78 */
79 if ((bsc->sc_dmadir & BSHW_READ) &&
80 count != bsc->sm_tdatalen)
81 {
82 s = "read count miss";
83 goto bad;
84 }
85 return;
86 }
87 else if (count == (u_int) sp->datalen)
88 {
89 return;
90 }
91
92 s = "strange count";
93 }
94 else
95 s = "extra smit interrupt";
96
97 bad:
98 bs_printf(ti, "smit_xfer_end", s);
99 ti->ti_error |= BSDMAABNORMAL;
100 }
101
102 /*********************************************************
103 * LOGITEC's SMIT TRANSFER
104 *********************************************************/
105
106 #define BSHW_LC_FSET 0x36
107 #define BSHW_LC_FCTRL 0x44
108 #define FCTRL_EN 0x01
109 #define FCTRL_WRITE 0x02
110
111 #define SF_ABORT 0x08
112 #define SF_RDY 0x10
113
114 #define LC_FSZ DEV_BSIZE
115 #define LC_SFSZ 0x0c
116 #define LC_REST (LC_FSZ - LC_SFSZ)
117
118 static BS_INLINE void
119 bshw_lc_smit_stop(bsc)
120 struct bs_softc *bsc;
121 {
122
123 write_wd33c93(bsc, BSHW_LC_FCTRL, 0);
124 BUS_IOW(cmd_port, CMDP_DMER);
125 }
126
127 static BS_INLINE void
128 bshw_lc_smit_start(bsc, count, direction)
129 struct bs_softc *bsc;
130 int count;
131 u_int direction;
132 {
133 u_int8_t pval, val = read_wd33c93(bsc, BSHW_LC_FSET);
134
135 bsc->sc_flags |= BSSMITSTART;
136 bshw_set_count(bsc, count);
137
138 pval = FCTRL_EN;
139 if ((direction & BSHW_READ) == 0)
140 pval |= (val & 0xe0) | FCTRL_WRITE;
141 write_wd33c93(bsc, BSHW_LC_FCTRL, pval);
142 bshw_start_xfer(bsc);
143 }
144
145 static int
146 bshw_lc_smit_fstat(bsc, wc, read)
147 struct bs_softc *bsc;
148 int wc, read;
149 {
150 u_int8_t stat;
151
152 #define ALWAYS_ABORT
153 #ifdef ALWAYS_ABORT
154 if (read == BSHW_READ)
155 {
156 while (wc -- > 0)
157 {
158 BUS_IO_WEIGHT;
159 stat = BUS_IOR(cmd_port);
160 if (stat & SF_RDY)
161 return 0;
162 if (stat & SF_ABORT)
163 return EIO;
164 }
165 }
166 else
167 {
168 #endif /* ALWAYS_ABORT */
169 while (wc -- > 0)
170 {
171 BUS_IO_WEIGHT;
172 stat = BUS_IOR(cmd_port);
173 if (stat & SF_ABORT)
174 return EIO;
175 if (stat & SF_RDY)
176 return 0;
177 }
178 #ifdef ALWAYS_ABORT
179 }
180 #endif /* ALWAYS_ABORT */
181
182 bs_poll_timeout(bsc, "bshw_lc_smit");
183 return EIO;
184 }
185
186 void
187 bs_lc_smit_xfer(ti, direction)
188 struct targ_info *ti;
189 u_int direction;
190 {
191 struct bs_softc *bsc = ti->ti_bsc;
192 struct sc_p *sp = &bsc->sc_p;
193 int datalen, count, wc = LC_SMIT_TIMEOUT * 1024 * 1024;
194 u_int8_t *data;
195
196 sp->bufp = NULL;
197 sp->seglen = 0;
198 data = sp->data;
199 datalen = sp->datalen;
200
201 bsc->sc_dmadir = direction;
202 bshw_set_dma_trans(bsc, ti->ti_cfgflags);
203 bshw_lc_smit_start(bsc, sp->datalen, direction);
204
205 if (direction & BSHW_READ)
206 {
207 do
208 {
209 if (bshw_lc_smit_fstat(bsc, wc, BSHW_READ))
210 break;
211
212 count = (datalen > LC_FSZ ? LC_FSZ : datalen);
213 #ifdef __FreeBSD__
214 memcopy((u_int8_t *)ti->sm_offset, data, count);
215 #else /* NetBSD */
216 bus_space_read_region_4(bsc->sc_memt, bsc->sc_memh,
217 ti->sm_offset, (u_int32_t *) data, count >> 2);
218 #endif /* NetBSD */
219 data += count;
220 datalen -= count;
221 }
222 while (datalen > 0);
223
224 bsc->sm_tdatalen = datalen;
225 }
226 else
227 {
228 do
229 {
230 if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
231 break;
232
233 count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
234 #ifdef __FreeBSD__
235 memcopy(data, (u_int8_t *)ti->sm_offset, count);
236 #else /* NetBSD */
237 bus_space_write_region_4(bsc->sc_memt, bsc->sc_memh,
238 ti->sm_offset, (u_int32_t *) data, count >> 2);
239 #endif /* NetBSD */
240 data += count;
241 datalen -= count;
242
243 if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
244 break;
245
246 count = (datalen > LC_REST ? LC_REST : datalen);
247 #ifdef __FreeBSD__
248 memcopy(data, (u_int8_t *)(ti->sm_offset + LC_SFSZ), count);
249 #else /* NetBSD */
250 bus_space_write_region_4(bsc->sc_memt, bsc->sc_memh,
251 ti->sm_offset + LC_SFSZ,
252 (u_int32_t *) data, count >> 2);
253 #endif /* NetBSD */
254 data += count;
255 datalen -= count;
256 }
257 while (datalen > 0);
258 }
259 }
Cache object: 361b09c49d6fca2d8b6355afa8054881
|