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