1 /* $NetBSD: mlhsc.c,v 1.34 2021/08/07 16:18:41 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)dma.c
32 */
33
34 /*
35 * Copyright (c) 1994 Michael L. Hitch
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 *
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 *
57 * @(#)dma.c
58 */
59
60 #include <sys/cdefs.h>
61 __KERNEL_RCSID(0, "$NetBSD: mlhsc.c,v 1.34 2021/08/07 16:18:41 thorpej Exp $");
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/kernel.h>
66 #include <sys/device.h>
67 #include <dev/scsipi/scsi_all.h>
68 #include <dev/scsipi/scsipi_all.h>
69 #include <dev/scsipi/scsiconf.h>
70 #include <amiga/amiga/device.h>
71 #include <amiga/amiga/isr.h>
72 #include <amiga/dev/scireg.h>
73 #include <amiga/dev/scivar.h>
74 #include <amiga/dev/zbusvar.h>
75
76 void mlhscattach(device_t, device_t, void *);
77 int mlhscmatch(device_t, cfdata_t, void *);
78
79 int mlhsc_dma_xfer_in(struct sci_softc *dev, int len,
80 register u_char *buf, int phase);
81 int mlhsc_dma_xfer_out(struct sci_softc *dev, int len,
82 register u_char *buf, int phase);
83
84 #ifdef DEBUG
85 extern int sci_debug;
86 #define QPRINTF(a) if (sci_debug > 1) printf a
87 #else
88 #define QPRINTF(a)
89 #endif
90
91 extern int sci_data_wait;
92
93 CFATTACH_DECL_NEW(mlhsc, sizeof(struct sci_softc),
94 mlhscmatch, mlhscattach, NULL, NULL);
95
96 /*
97 * if we are my Hacker's SCSI board we are here.
98 */
99 int
mlhscmatch(device_t parent,cfdata_t cf,void * aux)100 mlhscmatch(device_t parent, cfdata_t cf, void *aux)
101 {
102 struct zbus_args *zap;
103
104 zap = aux;
105
106 /*
107 * Check manufacturer and product id.
108 */
109 if (zap->manid == 2011 && zap->prodid == 1)
110 return(1);
111 else
112 return(0);
113 }
114
115 void
mlhscattach(device_t parent,device_t self,void * aux)116 mlhscattach(device_t parent, device_t self, void *aux)
117 {
118 volatile u_char *rp;
119 struct sci_softc *sc = device_private(self);
120 struct zbus_args *zap;
121 struct scsipi_adapter *adapt = &sc->sc_adapter;
122 struct scsipi_channel *chan = &sc->sc_channel;
123
124 sc->sc_dev = self;
125
126 printf("\n");
127
128 zap = aux;
129
130 rp = zap->va;
131 sc->sci_data = rp + 1;
132 sc->sci_odata = rp + 1;
133 sc->sci_icmd = rp + 3;
134 sc->sci_mode = rp + 5;
135 sc->sci_tcmd = rp + 7;
136 sc->sci_bus_csr = rp + 9;
137 sc->sci_sel_enb = rp + 9;
138 sc->sci_csr = rp + 11;
139 sc->sci_dma_send = rp + 11;
140 sc->sci_idata = rp + 13;
141 sc->sci_trecv = rp + 13;
142 sc->sci_iack = rp + 15;
143 sc->sci_irecv = rp + 15;
144
145 sc->dma_xfer_in = mlhsc_dma_xfer_in;
146 sc->dma_xfer_out = mlhsc_dma_xfer_out;
147
148 scireset(sc);
149
150 /*
151 * Fill in the scsipi_adapter.
152 */
153 memset(adapt, 0, sizeof(*adapt));
154 adapt->adapt_dev = self;
155 adapt->adapt_nchannels = 1;
156 adapt->adapt_openings = 7;
157 adapt->adapt_max_periph = 1;
158 adapt->adapt_request = sci_scsipi_request;
159 adapt->adapt_minphys = sci_minphys;
160
161 /*
162 * Fill in the scsipi_channel.
163 */
164 memset(chan, 0, sizeof(*chan));
165 chan->chan_adapter = adapt;
166 chan->chan_bustype = &scsi_bustype;
167 chan->chan_channel = 0;
168 chan->chan_ntargets = 8;
169 chan->chan_nluns = 8;
170 chan->chan_id = 7;
171
172 /*
173 * attach all scsi units on us
174 */
175 config_found(self, chan, scsiprint, CFARGS_NONE);
176 }
177
178 int
mlhsc_dma_xfer_in(struct sci_softc * dev,int len,register u_char * buf,int phase)179 mlhsc_dma_xfer_in(struct sci_softc *dev, int len, register u_char *buf,
180 int phase)
181 {
182 int wait = sci_data_wait;
183 u_char csr;
184 volatile register u_char *sci_dma = dev->sci_data + 16;
185 volatile register u_char *sci_csr = dev->sci_csr;
186 #ifdef DEBUG
187 u_char *obp = buf;
188 #endif
189
190 csr = *dev->sci_bus_csr;
191 __USE(csr);
192
193 QPRINTF(("mlhdma_in %d, csr=%02x\n", len, csr));
194
195 *dev->sci_tcmd = phase;
196 *dev->sci_mode |= SCI_MODE_DMA;
197 *dev->sci_icmd = 0;
198 *dev->sci_irecv = 0;
199 while (len > 128) {
200 wait = sci_data_wait;
201 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
202 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
203 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
204 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
205 || --wait < 0) {
206 #ifdef DEBUG
207 if (sci_debug)
208 printf("mlhdma_in fail: l%d i%x w%d\n",
209 len, csr, wait);
210 #endif
211 *dev->sci_mode &= ~SCI_MODE_DMA;
212 return 0;
213 }
214 }
215
216 #define R1 (*buf++ = *sci_dma)
217 R1; R1; R1; R1; R1; R1; R1; R1;
218 R1; R1; R1; R1; R1; R1; R1; R1;
219 R1; R1; R1; R1; R1; R1; R1; R1;
220 R1; R1; R1; R1; R1; R1; R1; R1;
221 R1; R1; R1; R1; R1; R1; R1; R1;
222 R1; R1; R1; R1; R1; R1; R1; R1;
223 R1; R1; R1; R1; R1; R1; R1; R1;
224 R1; R1; R1; R1; R1; R1; R1; R1;
225 R1; R1; R1; R1; R1; R1; R1; R1;
226 R1; R1; R1; R1; R1; R1; R1; R1;
227 R1; R1; R1; R1; R1; R1; R1; R1;
228 R1; R1; R1; R1; R1; R1; R1; R1;
229 R1; R1; R1; R1; R1; R1; R1; R1;
230 R1; R1; R1; R1; R1; R1; R1; R1;
231 R1; R1; R1; R1; R1; R1; R1; R1;
232 R1; R1; R1; R1; R1; R1; R1; R1;
233 len -= 128;
234 }
235 while (len > 0) {
236 wait = sci_data_wait;
237 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
238 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
239 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
240 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
241 || --wait < 0) {
242 #ifdef DEBUG
243 if (sci_debug)
244 printf("mlhdma_in fail: l%d i%x w%d\n",
245 len, csr, wait);
246 #endif
247 *dev->sci_mode &= ~SCI_MODE_DMA;
248 return 0;
249 }
250 }
251
252 *buf++ = *sci_dma;
253 len--;
254 }
255
256 QPRINTF(("mlhdma_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
257 len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
258 obp[6], obp[7], obp[8], obp[9]));
259
260 *dev->sci_mode &= ~SCI_MODE_DMA;
261 return 0;
262 }
263
264 int
mlhsc_dma_xfer_out(struct sci_softc * dev,int len,register u_char * buf,int phase)265 mlhsc_dma_xfer_out(struct sci_softc *dev, int len, register u_char *buf,
266 int phase)
267 {
268 int wait = sci_data_wait;
269 u_char csr;
270 volatile register u_char *sci_dma = dev->sci_data + 16;
271 volatile register u_char *sci_csr = dev->sci_csr;
272
273 csr = *dev->sci_bus_csr;
274 __USE(csr);
275
276 QPRINTF(("mlhdma_xfer %d, csr=%02x\n", len, csr));
277
278 QPRINTF(("mlhgdma_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
279 len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
280 buf[6], buf[7], buf[8], buf[9]));
281
282 *dev->sci_tcmd = phase;
283 *dev->sci_mode |= SCI_MODE_DMA;
284 *dev->sci_icmd = SCI_ICMD_DATA;
285 *dev->sci_dma_send = 0;
286 while (len > 64) {
287 wait = sci_data_wait;
288 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
289 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
290 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
291 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
292 || --wait < 0) {
293 #ifdef DEBUG
294 if (sci_debug)
295 printf("mlhdma_out fail: l%d i%x w%d\n",
296 len, csr, wait);
297 #endif
298 *dev->sci_mode &= ~SCI_MODE_DMA;
299 return 0;
300 }
301 }
302
303 #define W1 (*sci_dma = *buf++)
304 W1; W1; W1; W1; W1; W1; W1; W1;
305 W1; W1; W1; W1; W1; W1; W1; W1;
306 W1; W1; W1; W1; W1; W1; W1; W1;
307 W1; W1; W1; W1; W1; W1; W1; W1;
308 W1; W1; W1; W1; W1; W1; W1; W1;
309 W1; W1; W1; W1; W1; W1; W1; W1;
310 W1; W1; W1; W1; W1; W1; W1; W1;
311 W1; W1; W1; W1; W1; W1; W1; W1;
312 len -= 64;
313 }
314 while (len > 0) {
315 wait = sci_data_wait;
316 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) !=
317 (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) {
318 if (!(*sci_csr & SCI_CSR_PHASE_MATCH)
319 || !(*dev->sci_bus_csr & SCI_BUS_BSY)
320 || --wait < 0) {
321 #ifdef DEBUG
322 if (sci_debug)
323 printf("mlhdma_out fail: l%d i%x w%d\n",
324 len, csr, wait);
325 #endif
326 *dev->sci_mode &= ~SCI_MODE_DMA;
327 return 0;
328 }
329 }
330
331 *sci_dma = *buf++;
332 len--;
333 }
334
335 wait = sci_data_wait;
336 while ((*sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
337 SCI_CSR_PHASE_MATCH && --wait);
338
339 *dev->sci_mode &= ~SCI_MODE_DMA;
340 return 0;
341 }
342