esp.c revision 1.11 1 1.11 bouyer /* $NetBSD: esp.c,v 1.11 1997/08/27 11:23:48 bouyer Exp $ */
2 1.1 briggs
3 1.1 briggs /*
4 1.10 briggs * Copyright (c) 1997 Jason R. Thorpe.
5 1.10 briggs * All rights reserved.
6 1.1 briggs *
7 1.1 briggs * Redistribution and use in source and binary forms, with or without
8 1.1 briggs * modification, are permitted provided that the following conditions
9 1.1 briggs * are met:
10 1.1 briggs * 1. Redistributions of source code must retain the above copyright
11 1.1 briggs * notice, this list of conditions and the following disclaimer.
12 1.1 briggs * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 briggs * notice, this list of conditions and the following disclaimer in the
14 1.1 briggs * documentation and/or other materials provided with the distribution.
15 1.1 briggs * 3. All advertising materials mentioning features or use of this software
16 1.1 briggs * must display the following acknowledgement:
17 1.10 briggs * This product includes software developed for the NetBSD Project
18 1.10 briggs * by Jason R. Thorpe.
19 1.1 briggs * 4. The name of the author may not be used to endorse or promote products
20 1.1 briggs * derived from this software without specific prior written permission.
21 1.1 briggs *
22 1.1 briggs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 briggs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 briggs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 briggs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 briggs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 briggs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 briggs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 briggs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 briggs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 briggs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 briggs */
33 1.1 briggs
34 1.1 briggs /*
35 1.1 briggs * Copyright (c) 1994 Peter Galbavy
36 1.1 briggs * Copyright (c) 1995 Paul Kranenburg
37 1.1 briggs * All rights reserved.
38 1.1 briggs *
39 1.1 briggs * Redistribution and use in source and binary forms, with or without
40 1.1 briggs * modification, are permitted provided that the following conditions
41 1.1 briggs * are met:
42 1.1 briggs * 1. Redistributions of source code must retain the above copyright
43 1.1 briggs * notice, this list of conditions and the following disclaimer.
44 1.1 briggs * 2. Redistributions in binary form must reproduce the above copyright
45 1.1 briggs * notice, this list of conditions and the following disclaimer in the
46 1.1 briggs * documentation and/or other materials provided with the distribution.
47 1.1 briggs * 3. All advertising materials mentioning features or use of this software
48 1.1 briggs * must display the following acknowledgement:
49 1.1 briggs * This product includes software developed by Peter Galbavy
50 1.1 briggs * 4. The name of the author may not be used to endorse or promote products
51 1.1 briggs * derived from this software without specific prior written permission.
52 1.1 briggs *
53 1.1 briggs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
54 1.1 briggs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
55 1.1 briggs * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
56 1.1 briggs * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
57 1.1 briggs * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
58 1.1 briggs * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
59 1.1 briggs * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 1.1 briggs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
61 1.1 briggs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
62 1.1 briggs * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 1.1 briggs * POSSIBILITY OF SUCH DAMAGE.
64 1.1 briggs */
65 1.1 briggs
66 1.1 briggs /*
67 1.1 briggs * Based on aic6360 by Jarle Greipsland
68 1.1 briggs *
69 1.1 briggs * Acknowledgements: Many of the algorithms used in this driver are
70 1.1 briggs * inspired by the work of Julian Elischer (julian (at) tfs.com) and
71 1.1 briggs * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu). Thanks a million!
72 1.10 briggs */
73 1.10 briggs
74 1.10 briggs /*
75 1.10 briggs * Initial m68k mac support from Allen Briggs <briggs (at) macbsd.com>
76 1.10 briggs * (basically consisting of the match, a bit of the attach, and the
77 1.10 briggs * "DMA" glue functions).
78 1.1 briggs */
79 1.1 briggs
80 1.1 briggs #include <sys/types.h>
81 1.1 briggs #include <sys/param.h>
82 1.1 briggs #include <sys/systm.h>
83 1.1 briggs #include <sys/kernel.h>
84 1.1 briggs #include <sys/errno.h>
85 1.1 briggs #include <sys/ioctl.h>
86 1.1 briggs #include <sys/device.h>
87 1.1 briggs #include <sys/buf.h>
88 1.1 briggs #include <sys/proc.h>
89 1.1 briggs #include <sys/user.h>
90 1.1 briggs #include <sys/queue.h>
91 1.1 briggs
92 1.11 bouyer #include <dev/scsipi/scsi_all.h>
93 1.11 bouyer #include <dev/scsipi/scsipi_all.h>
94 1.11 bouyer #include <dev/scsipi/scsiconf.h>
95 1.11 bouyer #include <dev/scsipi/scsi_message.h>
96 1.1 briggs
97 1.1 briggs #include <machine/cpu.h>
98 1.1 briggs #include <machine/param.h>
99 1.1 briggs
100 1.7 briggs #include <dev/ic/ncr53c9xreg.h>
101 1.7 briggs #include <dev/ic/ncr53c9xvar.h>
102 1.7 briggs
103 1.1 briggs #include <machine/viareg.h>
104 1.1 briggs
105 1.1 briggs #include <mac68k/dev/espvar.h>
106 1.3 briggs
107 1.7 briggs void espattach __P((struct device *, struct device *, void *));
108 1.9 scottr int espmatch __P((struct device *, struct cfdata *, void *));
109 1.1 briggs
110 1.1 briggs /* Linkup to the rest of the kernel */
111 1.1 briggs struct cfattach esp_ca = {
112 1.1 briggs sizeof(struct esp_softc), espmatch, espattach
113 1.1 briggs };
114 1.1 briggs
115 1.1 briggs struct cfdriver esp_cd = {
116 1.1 briggs NULL, "esp", DV_DULL
117 1.1 briggs };
118 1.1 briggs
119 1.11 bouyer struct scsipi_adapter esp_switch = {
120 1.7 briggs ncr53c9x_scsi_cmd,
121 1.1 briggs minphys, /* no max at this level; handled by DMA code */
122 1.1 briggs NULL,
123 1.1 briggs NULL,
124 1.1 briggs };
125 1.1 briggs
126 1.11 bouyer struct scsipi_device esp_dev = {
127 1.1 briggs NULL, /* Use default error handler */
128 1.1 briggs NULL, /* have a queue, served by this */
129 1.1 briggs NULL, /* have no async handler */
130 1.1 briggs NULL, /* Use default 'done' routine */
131 1.1 briggs };
132 1.1 briggs
133 1.7 briggs /*
134 1.7 briggs * Functions and the switch for the MI code.
135 1.7 briggs */
136 1.7 briggs u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
137 1.7 briggs void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
138 1.7 briggs int esp_dma_isintr __P((struct ncr53c9x_softc *));
139 1.7 briggs void esp_dma_reset __P((struct ncr53c9x_softc *));
140 1.7 briggs int esp_dma_intr __P((struct ncr53c9x_softc *));
141 1.7 briggs int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
142 1.7 briggs size_t *, int, size_t *));
143 1.7 briggs void esp_dma_go __P((struct ncr53c9x_softc *));
144 1.7 briggs void esp_dma_stop __P((struct ncr53c9x_softc *));
145 1.7 briggs int esp_dma_isactive __P((struct ncr53c9x_softc *));
146 1.7 briggs
147 1.7 briggs struct ncr53c9x_glue esp_glue = {
148 1.7 briggs esp_read_reg,
149 1.7 briggs esp_write_reg,
150 1.7 briggs esp_dma_isintr,
151 1.7 briggs esp_dma_reset,
152 1.7 briggs esp_dma_intr,
153 1.7 briggs esp_dma_setup,
154 1.7 briggs esp_dma_go,
155 1.7 briggs esp_dma_stop,
156 1.7 briggs esp_dma_isactive,
157 1.7 briggs NULL, /* gl_clear_latched_intr */
158 1.7 briggs };
159 1.7 briggs
160 1.1 briggs int
161 1.9 scottr espmatch(parent, cf, aux)
162 1.1 briggs struct device *parent;
163 1.6 scottr struct cfdata *cf;
164 1.6 scottr void *aux;
165 1.1 briggs {
166 1.1 briggs if ((cf->cf_unit == 0) && mac68k_machine.scsi96)
167 1.1 briggs return (1);
168 1.1 briggs if ((cf->cf_unit == 1) && mac68k_machine.scsi96_2)
169 1.1 briggs return (1);
170 1.1 briggs return (0);
171 1.1 briggs }
172 1.1 briggs
173 1.1 briggs /*
174 1.1 briggs * Attach this instance, and then all the sub-devices
175 1.1 briggs */
176 1.1 briggs void
177 1.1 briggs espattach(parent, self, aux)
178 1.1 briggs struct device *parent, *self;
179 1.1 briggs void *aux;
180 1.1 briggs {
181 1.1 briggs extern vm_offset_t SCSIBase;
182 1.7 briggs struct esp_softc *esc = (void *)self;
183 1.7 briggs struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
184 1.1 briggs
185 1.1 briggs /*
186 1.7 briggs * Set up the glue for MI code early; we use some of it here.
187 1.1 briggs */
188 1.7 briggs sc->sc_glue = &esp_glue;
189 1.1 briggs
190 1.1 briggs /*
191 1.7 briggs * Save the regs
192 1.1 briggs */
193 1.1 briggs if (sc->sc_dev.dv_unit == 0) {
194 1.2 briggs unsigned long reg_offset;
195 1.2 briggs
196 1.7 briggs esc->sc_reg = (volatile u_char *) SCSIBase;
197 1.8 scottr via2_register_irq(VIA2_SCSIIRQ,
198 1.8 scottr (void (*)(void *))ncr53c9x_intr, esc);
199 1.7 briggs esc->irq_mask = V2IF_SCSIIRQ;
200 1.2 briggs reg_offset = SCSIBase - IOBase;
201 1.2 briggs if (reg_offset == 0x10000) {
202 1.2 briggs sc->sc_freq = 16500000;
203 1.2 briggs } else {
204 1.2 briggs sc->sc_freq = 25000000;
205 1.2 briggs }
206 1.1 briggs } else {
207 1.7 briggs esc->sc_reg = (volatile u_char *) SCSIBase + 0x402;
208 1.8 scottr via2_register_irq(VIA2_SCSIDRQ,
209 1.8 scottr (void (*)(void *))ncr53c9x_intr, esc);
210 1.7 briggs esc->irq_mask = V2IF_SCSIDRQ; /* V2IF_T1? */
211 1.2 briggs sc->sc_freq = 25000000;
212 1.1 briggs }
213 1.7 briggs
214 1.7 briggs printf(": address %p", esc->sc_reg);
215 1.1 briggs
216 1.1 briggs sc->sc_id = 7;
217 1.1 briggs
218 1.1 briggs /* gimme Mhz */
219 1.1 briggs sc->sc_freq /= 1000000;
220 1.1 briggs
221 1.1 briggs /*
222 1.1 briggs * It is necessary to try to load the 2nd config register here,
223 1.1 briggs * to find out what rev the esp chip is, else the esp_reset
224 1.1 briggs * will not set up the defaults correctly.
225 1.1 briggs */
226 1.7 briggs sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
227 1.7 briggs sc->sc_cfg2 = NCRCFG2_SCSI2;
228 1.3 briggs sc->sc_cfg3 = 0;
229 1.7 briggs sc->sc_rev = NCR_VARIANT_NCR53C96;
230 1.1 briggs
231 1.1 briggs /*
232 1.1 briggs * This is the value used to start sync negotiations
233 1.7 briggs * Note that the NCR register "SYNCTP" is programmed
234 1.1 briggs * in "clocks per byte", and has a minimum value of 4.
235 1.1 briggs * The SCSI period used in negotiation is one-fourth
236 1.1 briggs * of the time (in nanoseconds) needed to transfer one byte.
237 1.1 briggs * Since the chip's clock is given in MHz, we have the following
238 1.1 briggs * formula: 4 * period = (1000 / freq) * 4
239 1.1 briggs */
240 1.1 briggs sc->sc_minsync = 1000 / sc->sc_freq;
241 1.1 briggs
242 1.1 briggs sc->sc_minsync = 0; /* No synchronous xfers w/o DMA */
243 1.1 briggs /* Really no limit, but since we want to fit into the TCR... */
244 1.1 briggs sc->sc_maxxfer = 64 * 1024;
245 1.1 briggs
246 1.1 briggs /*
247 1.7 briggs * Now try to attach all the sub-devices
248 1.1 briggs */
249 1.7 briggs ncr53c9x_attach(sc, &esp_switch, &esp_dev);
250 1.1 briggs
251 1.1 briggs /*
252 1.7 briggs * Configure interrupts.
253 1.1 briggs */
254 1.1 briggs via2_reg(vPCR) = 0x22;
255 1.7 briggs via2_reg(vIFR) = esc->irq_mask;
256 1.7 briggs via2_reg(vIER) = 0x80 | esc->irq_mask;
257 1.1 briggs }
258 1.1 briggs
259 1.1 briggs /*
260 1.7 briggs * Glue functions.
261 1.1 briggs */
262 1.1 briggs
263 1.7 briggs u_char
264 1.7 briggs esp_read_reg(sc, reg)
265 1.7 briggs struct ncr53c9x_softc *sc;
266 1.7 briggs int reg;
267 1.1 briggs {
268 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
269 1.1 briggs
270 1.7 briggs return esc->sc_reg[reg * 16];
271 1.1 briggs }
272 1.1 briggs
273 1.1 briggs void
274 1.7 briggs esp_write_reg(sc, reg, val)
275 1.7 briggs struct ncr53c9x_softc *sc;
276 1.7 briggs int reg;
277 1.7 briggs u_char val;
278 1.1 briggs {
279 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
280 1.7 briggs u_char v = val;
281 1.1 briggs
282 1.7 briggs if (reg == NCR_CMD && v == (NCRCMD_TRANS|NCRCMD_DMA)) {
283 1.7 briggs v = NCRCMD_TRANS;
284 1.1 briggs }
285 1.7 briggs esc->sc_reg[reg * 16] = v;
286 1.1 briggs }
287 1.1 briggs
288 1.7 briggs int
289 1.7 briggs esp_dma_isintr(sc)
290 1.7 briggs struct ncr53c9x_softc *sc;
291 1.1 briggs {
292 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
293 1.1 briggs
294 1.7 briggs return esc->sc_reg[NCR_STAT * 16] & 0x80;
295 1.1 briggs }
296 1.1 briggs
297 1.1 briggs void
298 1.7 briggs esp_dma_reset(sc)
299 1.7 briggs struct ncr53c9x_softc *sc;
300 1.1 briggs {
301 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
302 1.1 briggs
303 1.7 briggs esc->sc_active = 0;
304 1.7 briggs esc->sc_tc = 0;
305 1.1 briggs }
306 1.1 briggs
307 1.7 briggs int
308 1.7 briggs esp_dma_intr(sc)
309 1.7 briggs struct ncr53c9x_softc *sc;
310 1.1 briggs {
311 1.7 briggs register struct esp_softc *esc = (struct esp_softc *)sc;
312 1.7 briggs register u_char *p;
313 1.7 briggs volatile u_char *cmdreg, *intrreg, *statreg, *fiforeg;
314 1.7 briggs register u_int espphase, espstat, espintr;
315 1.7 briggs register int cnt;
316 1.1 briggs
317 1.7 briggs if (esc->sc_active == 0) {
318 1.7 briggs printf("dma_intr--inactive DMA\n");
319 1.7 briggs return -1;
320 1.1 briggs }
321 1.1 briggs
322 1.7 briggs if ((sc->sc_espintr & NCRINTR_BS) == 0) {
323 1.7 briggs esc->sc_active = 0;
324 1.7 briggs return 0;
325 1.1 briggs }
326 1.1 briggs
327 1.7 briggs cnt = *esc->sc_pdmalen;
328 1.7 briggs if (*esc->sc_pdmalen == 0) {
329 1.7 briggs printf("data interrupt, but no count left.");
330 1.1 briggs }
331 1.1 briggs
332 1.7 briggs p = *esc->sc_dmaaddr;
333 1.7 briggs espphase = sc->sc_phase;
334 1.7 briggs espstat = (u_int) sc->sc_espstat;
335 1.7 briggs espintr = (u_int) sc->sc_espintr;
336 1.7 briggs cmdreg = esc->sc_reg + NCR_CMD * 16;
337 1.7 briggs fiforeg = esc->sc_reg + NCR_FIFO * 16;
338 1.7 briggs statreg = esc->sc_reg + NCR_STAT * 16;
339 1.7 briggs intrreg = esc->sc_reg + NCR_INTR * 16;
340 1.7 briggs do {
341 1.7 briggs if (esc->sc_datain) {
342 1.7 briggs *p++ = *fiforeg;
343 1.7 briggs cnt--;
344 1.7 briggs if (espphase == DATA_IN_PHASE) {
345 1.7 briggs *cmdreg = NCRCMD_TRANS;
346 1.7 briggs } else {
347 1.7 briggs esc->sc_active = 0;
348 1.7 briggs }
349 1.7 briggs } else {
350 1.7 briggs if ( (espphase == DATA_OUT_PHASE)
351 1.7 briggs || (espphase == MESSAGE_OUT_PHASE)) {
352 1.7 briggs *fiforeg = *p++;
353 1.7 briggs cnt--;
354 1.7 briggs *cmdreg = NCRCMD_TRANS;
355 1.7 briggs } else {
356 1.7 briggs esc->sc_active = 0;
357 1.7 briggs }
358 1.1 briggs }
359 1.1 briggs
360 1.7 briggs if (esc->sc_active) {
361 1.7 briggs while (!(*statreg & 0x80));
362 1.7 briggs espstat = *statreg;
363 1.7 briggs espintr = *intrreg;
364 1.7 briggs espphase = (espintr & NCRINTR_DIS)
365 1.7 briggs ? /* Disconnected */ BUSFREE_PHASE
366 1.7 briggs : espstat & PHASE_MASK;
367 1.1 briggs }
368 1.7 briggs } while (esc->sc_active && (espintr & NCRINTR_BS));
369 1.7 briggs sc->sc_phase = espphase;
370 1.7 briggs sc->sc_espstat = (u_char) espstat;
371 1.7 briggs sc->sc_espintr = (u_char) espintr;
372 1.7 briggs *esc->sc_dmaaddr = p;
373 1.7 briggs *esc->sc_pdmalen = cnt;
374 1.1 briggs
375 1.7 briggs if (*esc->sc_pdmalen == 0) {
376 1.7 briggs esc->sc_tc = NCRSTAT_TC;
377 1.1 briggs }
378 1.7 briggs sc->sc_espstat |= esc->sc_tc;
379 1.7 briggs return 0;
380 1.1 briggs }
381 1.1 briggs
382 1.1 briggs int
383 1.7 briggs esp_dma_setup(sc, addr, len, datain, dmasize)
384 1.7 briggs struct ncr53c9x_softc *sc;
385 1.7 briggs caddr_t *addr;
386 1.7 briggs size_t *len;
387 1.7 briggs int datain;
388 1.7 briggs size_t *dmasize;
389 1.1 briggs {
390 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
391 1.1 briggs
392 1.7 briggs esc->sc_dmaaddr = addr;
393 1.7 briggs esc->sc_pdmalen = len;
394 1.7 briggs esc->sc_datain = datain;
395 1.7 briggs esc->sc_dmasize = *dmasize;
396 1.7 briggs esc->sc_tc = 0;
397 1.1 briggs
398 1.7 briggs return 0;
399 1.1 briggs }
400 1.1 briggs
401 1.1 briggs void
402 1.7 briggs esp_dma_go(sc)
403 1.7 briggs struct ncr53c9x_softc *sc;
404 1.1 briggs {
405 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
406 1.1 briggs
407 1.7 briggs if (esc->sc_datain == 0) {
408 1.7 briggs esc->sc_reg[NCR_FIFO * 16] = **esc->sc_dmaaddr;
409 1.7 briggs (*esc->sc_pdmalen)--;
410 1.7 briggs (*esc->sc_dmaaddr)++;
411 1.1 briggs }
412 1.7 briggs esc->sc_active = 1;
413 1.1 briggs }
414 1.1 briggs
415 1.1 briggs void
416 1.7 briggs esp_dma_stop(sc)
417 1.7 briggs struct ncr53c9x_softc *sc;
418 1.1 briggs {
419 1.1 briggs }
420 1.1 briggs
421 1.1 briggs int
422 1.7 briggs esp_dma_isactive(sc)
423 1.7 briggs struct ncr53c9x_softc *sc;
424 1.1 briggs {
425 1.7 briggs struct esp_softc *esc = (struct esp_softc *)sc;
426 1.1 briggs
427 1.7 briggs return esc->sc_active;
428 1.1 briggs }
429