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