ncr.c revision 1.24 1 /* $NetBSD: ncr.c,v 1.24 2000/01/24 02:40:35 matt Exp $ */
2
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Adam Glass, David Jones, Gordon W. Ross, and Jens A. Nilsson.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * This file contains the machine-dependent parts of the NCR-5380
41 * controller. The machine-independent parts are in ncr5380sbc.c.
42 *
43 * Note: Only PIO transfers for now which implicates very bad
44 * performance. DMA support will come soon.
45 *
46 * Jens A. Nilsson.
47 *
48 * Credits:
49 *
50 * This code is based on arch/sun3/dev/si*
51 * Written by David Jones, Gordon Ross, and Adam Glass.
52 */
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/errno.h>
57 #include <sys/kernel.h>
58 #include <sys/malloc.h>
59 #include <sys/device.h>
60 #include <sys/buf.h>
61 #include <sys/proc.h>
62 #include <sys/user.h>
63
64 #include <vm/vm.h>
65 #include <vm/vm_kern.h>
66
67 #include <dev/scsipi/scsi_all.h>
68 #include <dev/scsipi/scsipi_all.h>
69 #include <dev/scsipi/scsipi_debug.h>
70 #include <dev/scsipi/scsiconf.h>
71
72 #include <dev/ic/ncr5380reg.h>
73 #include <dev/ic/ncr5380var.h>
74
75 #include <machine/cpu.h>
76 #include <machine/vsbus.h>
77 #include <machine/bus.h>
78 #include <machine/sid.h>
79 #include <machine/scb.h>
80
81 #include "ioconf.h"
82
83 #define MIN_DMA_LEN 128
84
85 struct si_dma_handle {
86 int dh_flags;
87 #define SIDH_BUSY 1
88 #define SIDH_OUT 2
89 caddr_t dh_addr;
90 int dh_len;
91 struct proc *dh_proc;
92 };
93
94 struct si_softc {
95 struct ncr5380_softc ncr_sc;
96 caddr_t ncr_addr;
97 int ncr_off;
98 int ncr_dmaaddr;
99 int ncr_dmacount;
100 int ncr_dmadir;
101 struct si_dma_handle ncr_dma[SCI_OPENINGS];
102 };
103
104 /* This is copied from julian's bt driver */
105 /* "so we have a default dev struct for our link struct." */
106 static struct scsipi_device si_dev = {
107 NULL, /* Use default error handler. */
108 NULL, /* Use default start handler. */
109 NULL, /* Use default async handler. */
110 NULL, /* Use default "done" routine. */
111 };
112
113 static int si_match(struct device *, struct cfdata *, void *);
114 static void si_attach(struct device *, struct device *, void *);
115 static void si_minphys(struct buf *);
116
117 static void si_dma_alloc __P((struct ncr5380_softc *));
118 static void si_dma_free __P((struct ncr5380_softc *));
119 static void si_dma_setup __P((struct ncr5380_softc *));
120 static void si_dma_start __P((struct ncr5380_softc *));
121 static void si_dma_poll __P((struct ncr5380_softc *));
122 static void si_dma_eop __P((struct ncr5380_softc *));
123 static void si_dma_stop __P((struct ncr5380_softc *));
124
125
126 struct cfattach ncr_ca = {
127 sizeof(struct si_softc), si_match, si_attach
128 };
129
130 static int
131 si_match(parent, cf, aux)
132 struct device *parent;
133 struct cfdata *cf;
134 void *aux;
135 {
136 struct vsbus_attach_args *va = aux;
137 volatile char *si_csr = (char *) va->va_addr;
138
139 if (vax_boardtype == VAX_BTYP_49)
140 return 0;
141 /* This is the way Linux autoprobes the interrupt MK-990321 */
142 si_csr[12] = 0;
143 si_csr[16] = 0x80;
144 si_csr[0] = 0x80;
145 si_csr[4] = 5; /* 0xcf */
146 DELAY(100000);
147 return 1;
148 }
149
150 static void
151 si_attach(parent, self, aux)
152 struct device *parent, *self;
153 void *aux;
154 {
155 struct vsbus_attach_args *va = aux;
156 struct si_softc *sc = (struct si_softc *) self;
157 struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
158
159 printf("\n");
160
161 scb_vecalloc(va->va_cvec, (void (*)(void *)) ncr5380_intr, sc, SCB_ISTACK);
162
163 /*
164 * DMA area mapin.
165 * On VS3100, split the 128K block between the two devices.
166 * On VS2000, don't care for now.
167 */
168 #define DMASIZE (64*1024)
169 if (vax_boardtype != VAX_BTYP_410) {
170 if (va->va_paddr & 0x100) /* Magic */
171 sc->ncr_off = DMASIZE;
172 sc->ncr_addr = (caddr_t)uvm_km_valloc(kernel_map, DMASIZE);
173
174 ioaccess((vaddr_t)sc->ncr_addr,
175 0x202d0000 + sc->ncr_off, DMASIZE/VAX_NBPG);
176
177 /*
178 * MD function pointers used by the MI code.
179 */
180 ncr_sc->sc_dma_alloc = si_dma_alloc;
181 ncr_sc->sc_dma_free = si_dma_free;
182 ncr_sc->sc_dma_setup = si_dma_setup;
183 ncr_sc->sc_dma_start = si_dma_start;
184 ncr_sc->sc_dma_poll = si_dma_poll;
185 ncr_sc->sc_dma_eop = si_dma_eop;
186 ncr_sc->sc_dma_stop = si_dma_stop;
187
188 /* DMA control register offsets */
189 sc->ncr_dmaaddr = 32; /* DMA address in buffer, longword */
190 sc->ncr_dmacount = 64; /* DMA count register */
191 sc->ncr_dmadir = 68; /* Direction of DMA transfer */
192 }
193 ncr_sc->sc_pio_out = ncr5380_pio_out;
194 ncr_sc->sc_pio_in = ncr5380_pio_in;
195
196 ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
197
198 /*
199 * Fill in the adapter.
200 */
201 ncr_sc->sc_adapter.scsipi_cmd = ncr5380_scsi_cmd;
202 ncr_sc->sc_adapter.scsipi_minphys = si_minphys;
203
204 /*
205 * Fill in the prototype scsi_link.
206 */
207 ncr_sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
208 ncr_sc->sc_link.adapter_softc = sc;
209 ncr_sc->sc_link.scsipi_scsi.adapter_target = 7;
210 ncr_sc->sc_link.adapter = &ncr_sc->sc_adapter;
211 ncr_sc->sc_link.device = &si_dev;
212 ncr_sc->sc_link.type = BUS_SCSI;
213
214 /*
215 * Initialize fields used by the MI code.
216 */
217 /* ncr_sc->sc_regt = Unused on VAX */
218 ncr_sc->sc_regh = vax_map_physmem(va->va_paddr, 1);
219
220 /* Register offsets */
221 ncr_sc->sci_r0 = 0;
222 ncr_sc->sci_r1 = 4;
223 ncr_sc->sci_r2 = 8;
224 ncr_sc->sci_r3 = 12;
225 ncr_sc->sci_r4 = 16;
226 ncr_sc->sci_r5 = 20;
227 ncr_sc->sci_r6 = 24;
228 ncr_sc->sci_r7 = 28;
229
230 ncr_sc->sc_no_disconnect = 0xff;
231 /*
232 * Initialize si board itself.
233 */
234 ncr5380_init(ncr_sc);
235 ncr5380_reset_scsibus(ncr_sc);
236
237 config_found(&(ncr_sc->sc_dev), &(ncr_sc->sc_link), scsiprint);
238 }
239
240 /*
241 * Adjust the max transfer size. The DMA buffer is only 16k on VS2000.
242 */
243 static void
244 si_minphys(struct buf *bp)
245 {
246 if ((vax_boardtype == VAX_BTYP_410) && (bp->b_bcount > (16*1024)))
247 bp->b_bcount = (16*1024);
248 else if (bp->b_bcount > MAXPHYS)
249 bp->b_bcount = MAXPHYS;
250 }
251
252 void
253 si_dma_alloc(ncr_sc)
254 struct ncr5380_softc *ncr_sc;
255 {
256 struct si_softc *sc = (struct si_softc *)ncr_sc;
257 struct sci_req *sr = ncr_sc->sc_current;
258 struct scsipi_xfer *xs = sr->sr_xs;
259 struct si_dma_handle *dh;
260 int xlen, i;
261
262 #ifdef DIAGNOSTIC
263 if (sr->sr_dma_hand != NULL)
264 panic("si_dma_alloc: already have DMA handle");
265 #endif
266
267 /* Polled transfers shouldn't allocate a DMA handle. */
268 if (sr->sr_flags & SR_IMMED)
269 return;
270
271 xlen = ncr_sc->sc_datalen;
272
273 /* Make sure our caller checked sc_min_dma_len. */
274 if (xlen < MIN_DMA_LEN)
275 panic("si_dma_alloc: len=0x%x\n", xlen);
276
277 /*
278 * Find free PDMA handle. Guaranteed to find one since we
279 * have as many PDMA handles as the driver has processes.
280 * (instances?)
281 */
282 for (i = 0; i < SCI_OPENINGS; i++) {
283 if ((sc->ncr_dma[i].dh_flags & SIDH_BUSY) == 0)
284 goto found;
285 }
286 panic("sbc: no free PDMA handles");
287 found:
288 dh = &sc->ncr_dma[i];
289 dh->dh_flags = SIDH_BUSY;
290 dh->dh_addr = ncr_sc->sc_dataptr;
291 dh->dh_len = xlen;
292 dh->dh_proc = xs->bp->b_proc;
293
294 /* Remember dest buffer parameters */
295 if (xs->xs_control & XS_CTL_DATA_OUT)
296 dh->dh_flags |= SIDH_OUT;
297
298 sr->sr_dma_hand = dh;
299 }
300
301 void
302 si_dma_free(ncr_sc)
303 struct ncr5380_softc *ncr_sc;
304 {
305 struct sci_req *sr = ncr_sc->sc_current;
306 struct si_dma_handle *dh = sr->sr_dma_hand;
307
308 if (dh->dh_flags & SIDH_BUSY)
309 dh->dh_flags = 0;
310 else
311 printf("si_dma_free: free'ing unused buffer\n");
312
313 sr->sr_dma_hand = NULL;
314 }
315
316 void
317 si_dma_setup(ncr_sc)
318 struct ncr5380_softc *ncr_sc;
319 {
320 /* Do nothing here */
321 }
322
323 void
324 si_dma_start(ncr_sc)
325 struct ncr5380_softc *ncr_sc;
326 {
327 struct si_softc *sc = (struct si_softc *)ncr_sc;
328 struct sci_req *sr = ncr_sc->sc_current;
329 struct si_dma_handle *dh = sr->sr_dma_hand;
330
331 /*
332 * Set the VAX-DMA-specific registers, and copy the data if
333 * it is directed "outbound".
334 */
335 if (dh->dh_flags & SIDH_OUT) {
336 if ((vaddr_t)dh->dh_addr & KERNBASE)
337 bcopy(dh->dh_addr, sc->ncr_addr, dh->dh_len);
338 else
339 vsbus_copyfromproc(dh->dh_proc, dh->dh_addr,
340 sc->ncr_addr, dh->dh_len);
341 bus_space_write_1(ncr_sc->sc_regt, ncr_sc->sc_regh,
342 sc->ncr_dmadir, 0);
343 } else {
344 bus_space_write_1(ncr_sc->sc_regt, ncr_sc->sc_regh,
345 sc->ncr_dmadir, 1);
346 }
347 bus_space_write_4(ncr_sc->sc_regt, ncr_sc->sc_regh,
348 sc->ncr_dmacount, -dh->dh_len);
349 bus_space_write_4(ncr_sc->sc_regt, ncr_sc->sc_regh,
350 sc->ncr_dmaaddr, sc->ncr_off);
351 /*
352 * Now from the 5380-internal DMA registers.
353 */
354 if (dh->dh_flags & SIDH_OUT) {
355 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_OUT);
356 NCR5380_WRITE(ncr_sc, sci_icmd, SCI_ICMD_DATA);
357 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode)
358 | SCI_MODE_DMA | SCI_MODE_DMA_IE);
359 NCR5380_WRITE(ncr_sc, sci_dma_send, 0);
360 } else {
361 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_IN);
362 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
363 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode)
364 | SCI_MODE_DMA | SCI_MODE_DMA_IE);
365 NCR5380_WRITE(ncr_sc, sci_irecv, 0);
366 }
367 ncr_sc->sc_state |= NCR_DOINGDMA;
368 }
369
370 /*
371 * When?
372 */
373 void
374 si_dma_poll(ncr_sc)
375 struct ncr5380_softc *ncr_sc;
376 {
377 printf("si_dma_poll\n");
378 }
379
380 /*
381 * When?
382 */
383 void
384 si_dma_eop(ncr_sc)
385 struct ncr5380_softc *ncr_sc;
386 {
387 printf("si_dma_eop\n");
388 }
389
390 void
391 si_dma_stop(ncr_sc)
392 struct ncr5380_softc *ncr_sc;
393 {
394 struct si_softc *sc = (struct si_softc *)ncr_sc;
395 struct sci_req *sr = ncr_sc->sc_current;
396 struct si_dma_handle *dh = sr->sr_dma_hand;
397 int count, i;
398
399 if (ncr_sc->sc_state & NCR_DOINGDMA)
400 ncr_sc->sc_state &= ~NCR_DOINGDMA;
401
402 /*
403 * Sometimes the FIFO buffer isn't drained when the
404 * interrupt is posted. Just loop here and hope that
405 * it will drain soon.
406 */
407 for (i = 0; i < 20000; i++) {
408 count = bus_space_read_4(ncr_sc->sc_regt,
409 ncr_sc->sc_regh, sc->ncr_dmacount);
410 if (count == 0)
411 break;
412 DELAY(100);
413 }
414 if (count == 0) {
415 if (((dh->dh_flags & SIDH_OUT) == 0)) {
416 if ((vaddr_t)dh->dh_addr & KERNBASE)
417 bcopy(sc->ncr_addr, dh->dh_addr, dh->dh_len);
418 else
419 vsbus_copytoproc(dh->dh_proc, sc->ncr_addr,
420 dh->dh_addr, dh->dh_len);
421
422 }
423 ncr_sc->sc_dataptr += dh->dh_len;
424 ncr_sc->sc_datalen -= dh->dh_len;
425 }
426
427 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode) &
428 ~(SCI_MODE_DMA | SCI_MODE_DMA_IE));
429 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
430 }
431