1 /* $NetBSD: ncr.c,v 1.52 2024/02/17 17:41:43 tsutsui 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 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * This file contains the machine-dependent parts of the NCR-5380
34 * controller. The machine-independent parts are in ncr5380sbc.c.
35 *
36 * Jens A. Nilsson.
37 *
38 * Credits:
39 *
40 * This code is based on arch/sun3/dev/si*
41 * Written by David Jones, Gordon Ross, and Adam Glass.
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: ncr.c,v 1.52 2024/02/17 17:41:43 tsutsui Exp $");
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/buf.h>
50 #include <sys/bus.h>
51 #include <sys/cpu.h>
52 #include <sys/device.h>
53 #include <sys/errno.h>
54 #include <sys/kernel.h>
55 #include <sys/proc.h>
56
57 #include <dev/scsipi/scsi_all.h>
58 #include <dev/scsipi/scsipi_all.h>
59 #include <dev/scsipi/scsipi_debug.h>
60 #include <dev/scsipi/scsiconf.h>
61
62 #include <dev/ic/ncr5380reg.h>
63 #include <dev/ic/ncr5380var.h>
64
65 #include <machine/vsbus.h>
66 #include <machine/sid.h>
67 #include <machine/scb.h>
68 #include <machine/clock.h>
69 #include <machine/ka420.h>
70
71 #include "ioconf.h"
72
73 #define MIN_DMA_LEN 128
74
75 struct si_dma_handle {
76 int dh_flags;
77 #define SIDH_BUSY 1
78 #define SIDH_OUT 2
79 void *dh_addr;
80 int dh_len;
81 struct proc *dh_proc;
82 };
83
84 struct si_softc {
85 struct ncr5380_softc ncr_sc;
86 struct evcnt ncr_intrcnt;
87 void *ncr_addr;
88 int ncr_off;
89 int ncr_dmaaddr;
90 int ncr_dmacount;
91 int ncr_dmadir;
92 struct si_dma_handle ncr_dma[SCI_OPENINGS];
93 struct vsbus_dma sc_vd;
94 int onlyscsi; /* This machine needs no queueing */
95 };
96
97 static int ncr_dmasize;
98
99 static int si_vsbus_match(device_t, cfdata_t, void *);
100 static void si_vsbus_attach(device_t, device_t, void *);
101 static void si_minphys(struct buf *);
102
103 static void si_dma_alloc(struct ncr5380_softc *);
104 static void si_dma_free(struct ncr5380_softc *);
105 static void si_dma_setup(struct ncr5380_softc *);
106 static void si_dma_start(struct ncr5380_softc *);
107 static void si_dma_poll(struct ncr5380_softc *);
108 static void si_dma_eop(struct ncr5380_softc *);
109 static void si_dma_stop(struct ncr5380_softc *);
110 static void si_dma_go(void *);
111
112 CFATTACH_DECL_NEW(si_vsbus, sizeof(struct si_softc),
113 si_vsbus_match, si_vsbus_attach, NULL, NULL);
114
115 static int
si_vsbus_match(device_t parent,cfdata_t cf,void * aux)116 si_vsbus_match(device_t parent, cfdata_t cf, void *aux)
117 {
118 struct vsbus_attach_args * const va = aux;
119 volatile char *si_csr = (char *) va->va_addr;
120
121 if (vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_46
122 || vax_boardtype == VAX_BTYP_48 || vax_boardtype == VAX_BTYP_53)
123 return 0;
124 /* This is the way Linux autoprobes the interrupt MK-990321 */
125 si_csr[12] = 0;
126 si_csr[16] = 0x80;
127 si_csr[0] = 0x80;
128 si_csr[4] = 5; /* 0xcf */
129 DELAY(100000);
130 return 1;
131 }
132
133 static void
si_vsbus_attach(device_t parent,device_t self,void * aux)134 si_vsbus_attach(device_t parent, device_t self, void *aux)
135 {
136 struct vsbus_attach_args * const va = aux;
137 struct si_softc * const sc = device_private(self);
138 struct ncr5380_softc * const ncr_sc = &sc->ncr_sc;
139 int tweak, target;
140
141 ncr_sc->sc_dev = self;
142
143 scb_vecalloc(va->va_cvec, (void (*)(void *)) ncr5380_intr, sc,
144 SCB_ISTACK, &sc->ncr_intrcnt);
145 evcnt_attach_dynamic(&sc->ncr_intrcnt, EVCNT_TYPE_INTR, NULL,
146 device_xname(self), "intr");
147
148 /*
149 * DMA area mapin.
150 * On VS3100, split the 128K block between the two devices.
151 * On VS2000, don't care for now.
152 */
153 #define DMASIZE (64*1024)
154 if (va->va_paddr & 0x100) { /* Secondary SCSI controller */
155 sc->ncr_off = DMASIZE;
156 sc->onlyscsi = 1;
157 }
158 sc->ncr_addr = (void *)va->va_dmaaddr;
159 ncr_dmasize = uimin(va->va_dmasize, MAXPHYS);
160
161 /*
162 * MD function pointers used by the MI code.
163 */
164 ncr_sc->sc_dma_alloc = si_dma_alloc;
165 ncr_sc->sc_dma_free = si_dma_free;
166 ncr_sc->sc_dma_setup = si_dma_setup;
167 ncr_sc->sc_dma_start = si_dma_start;
168 ncr_sc->sc_dma_poll = si_dma_poll;
169 ncr_sc->sc_dma_eop = si_dma_eop;
170 ncr_sc->sc_dma_stop = si_dma_stop;
171
172 /* DMA control register offsets */
173 sc->ncr_dmaaddr = 32; /* DMA address in buffer, longword */
174 sc->ncr_dmacount = 64; /* DMA count register */
175 sc->ncr_dmadir = 68; /* Direction of DMA transfer */
176
177 ncr_sc->sc_pio_out = ncr5380_pio_out;
178 ncr_sc->sc_pio_in = ncr5380_pio_in;
179
180 ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
181
182 /*
183 * Initialize fields used by the MI code.
184 */
185 /* ncr_sc->sc_regt = Unused on VAX */
186 ncr_sc->sc_regh = vax_map_physmem(va->va_paddr, 1);
187
188 /* Register offsets */
189 ncr_sc->sci_r0 = 0;
190 ncr_sc->sci_r1 = 4;
191 ncr_sc->sci_r2 = 8;
192 ncr_sc->sci_r3 = 12;
193 ncr_sc->sci_r4 = 16;
194 ncr_sc->sci_r5 = 20;
195 ncr_sc->sci_r6 = 24;
196 ncr_sc->sci_r7 = 28;
197
198 ncr_sc->sc_rev = NCR_VARIANT_NCR5380;
199
200 ncr_sc->sc_no_disconnect = 0xff;
201
202 /*
203 * Get the SCSI chip target address out of NVRAM.
204 * This do not apply to the VS2000.
205 */
206 tweak = clk_tweak + (va->va_paddr & 0x100 ? 3 : 0);
207 if (vax_boardtype == VAX_BTYP_410)
208 target = 7;
209 else
210 target = (clk_page[0xbc/2] >> tweak) & 7;
211
212 /*
213 * Explicitly enable upto 128KB "Big DMA" on KA420.
214 * (It looks KA420 firmware doesn't enable it on network boot)
215 */
216 #define STC_MODE_OFF (KA420_STC_MODE - KA420_SCS_BASE)
217 if (vax_boardtype == VAX_BTYP_420) {
218 bus_space_write_1(ncr_sc->sc_regt, ncr_sc->sc_regh,
219 STC_MODE_OFF, 1);
220 }
221
222 aprint_normal("\n");
223 aprint_normal_dev(self, "NCR5380, SCSI ID %d\n", target);
224
225 ncr_sc->sc_adapter.adapt_minphys = si_minphys;
226 ncr_sc->sc_channel.chan_id = target;
227
228 /*
229 * Init the vsbus DMA resource queue struct */
230 sc->sc_vd.vd_go = si_dma_go;
231 sc->sc_vd.vd_arg = sc;
232
233 /*
234 * Initialize si board itself.
235 */
236 ncr5380_attach(ncr_sc);
237 }
238
239 /*
240 * Adjust the max transfer size. The DMA buffer is only 16k on VS2000.
241 */
242 static void
si_minphys(struct buf * bp)243 si_minphys(struct buf *bp)
244 {
245 if (bp->b_bcount > ncr_dmasize)
246 bp->b_bcount = ncr_dmasize;
247 }
248
249 void
si_dma_alloc(struct ncr5380_softc * ncr_sc)250 si_dma_alloc(struct ncr5380_softc *ncr_sc)
251 {
252 struct si_softc *sc = (struct si_softc *)ncr_sc;
253 struct sci_req *sr = ncr_sc->sc_current;
254 struct scsipi_xfer *xs = sr->sr_xs;
255 struct si_dma_handle *dh;
256 int xlen, i;
257
258 #ifdef DIAGNOSTIC
259 if (sr->sr_dma_hand != NULL)
260 panic("si_dma_alloc: already have DMA handle");
261 #endif
262
263 /* Polled transfers shouldn't allocate a DMA handle. */
264 if (sr->sr_flags & SR_IMMED)
265 return;
266
267 xlen = ncr_sc->sc_datalen;
268
269 /* Make sure our caller checked sc_min_dma_len. */
270 if (xlen < MIN_DMA_LEN)
271 panic("si_dma_alloc: len=0x%x", xlen);
272
273 /*
274 * Find free PDMA handle. Guaranteed to find one since we
275 * have as many PDMA handles as the driver has processes.
276 * (instances?)
277 */
278 for (i = 0; i < SCI_OPENINGS; i++) {
279 if ((sc->ncr_dma[i].dh_flags & SIDH_BUSY) == 0)
280 goto found;
281 }
282 panic("sbc: no free PDMA handles");
283 found:
284 dh = &sc->ncr_dma[i];
285 dh->dh_flags = SIDH_BUSY;
286 dh->dh_addr = ncr_sc->sc_dataptr;
287 dh->dh_len = xlen;
288 if (((vaddr_t)ncr_sc->sc_dataptr & KERNBASE) == 0) {
289 if (xs->bp == NULL)
290 panic("si_dma_alloc");
291 dh->dh_proc = xs->bp->b_proc;
292 }
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
si_dma_free(struct ncr5380_softc * ncr_sc)302 si_dma_free(struct ncr5380_softc *ncr_sc)
303 {
304 struct sci_req *sr = ncr_sc->sc_current;
305 struct si_dma_handle *dh = sr->sr_dma_hand;
306
307 if (dh->dh_flags & SIDH_BUSY)
308 dh->dh_flags = 0;
309 else
310 printf("si_dma_free: free'ing unused buffer\n");
311
312 sr->sr_dma_hand = NULL;
313 }
314
315 void
si_dma_setup(struct ncr5380_softc * ncr_sc)316 si_dma_setup(struct ncr5380_softc *ncr_sc)
317 {
318 /* Do nothing here */
319 }
320
321 void
si_dma_start(struct ncr5380_softc * ncr_sc)322 si_dma_start(struct ncr5380_softc *ncr_sc)
323 {
324 struct si_softc *sc = (struct si_softc *)ncr_sc;
325
326 /* Just put on queue; will call go() from below */
327 if (sc->onlyscsi)
328 si_dma_go(ncr_sc);
329 else
330 vsbus_dma_start(&sc->sc_vd);
331 }
332
333 /*
334 * go() routine called when another transfer somewhere is finished.
335 */
336 void
si_dma_go(void * arg)337 si_dma_go(void *arg)
338 {
339 struct ncr5380_softc *ncr_sc = arg;
340 struct si_softc *sc = (struct si_softc *)ncr_sc;
341 struct sci_req *sr = ncr_sc->sc_current;
342 struct si_dma_handle *dh = sr->sr_dma_hand;
343
344 /*
345 * Set the VAX-DMA-specific registers, and copy the data if
346 * it is directed "outbound".
347 */
348 if (dh->dh_flags & SIDH_OUT) {
349 vsbus_copyfromproc(dh->dh_proc, dh->dh_addr,
350 (char *)sc->ncr_addr + sc->ncr_off, dh->dh_len);
351 bus_space_write_1(ncr_sc->sc_regt, ncr_sc->sc_regh,
352 sc->ncr_dmadir, 0);
353 } else {
354 bus_space_write_1(ncr_sc->sc_regt, ncr_sc->sc_regh,
355 sc->ncr_dmadir, 1);
356 }
357 bus_space_write_4(ncr_sc->sc_regt, ncr_sc->sc_regh,
358 sc->ncr_dmacount, -dh->dh_len);
359 bus_space_write_4(ncr_sc->sc_regt, ncr_sc->sc_regh,
360 sc->ncr_dmaaddr, sc->ncr_off);
361 /*
362 * Now from the 5380-internal DMA registers.
363 */
364 if (dh->dh_flags & SIDH_OUT) {
365 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_OUT);
366 NCR5380_WRITE(ncr_sc, sci_icmd, SCI_ICMD_DATA);
367 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode)
368 | SCI_MODE_DMA | SCI_MODE_DMA_IE);
369 NCR5380_WRITE(ncr_sc, sci_dma_send, 0);
370 } else {
371 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_IN);
372 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
373 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode)
374 | SCI_MODE_DMA | SCI_MODE_DMA_IE);
375 NCR5380_WRITE(ncr_sc, sci_irecv, 0);
376 }
377 ncr_sc->sc_state |= NCR_DOINGDMA;
378 }
379
380 /*
381 * When?
382 */
383 void
si_dma_poll(struct ncr5380_softc * ncr_sc)384 si_dma_poll(struct ncr5380_softc *ncr_sc)
385 {
386 printf("si_dma_poll\n");
387 }
388
389 /*
390 * When?
391 */
392 void
si_dma_eop(struct ncr5380_softc * ncr_sc)393 si_dma_eop(struct ncr5380_softc *ncr_sc)
394 {
395 printf("si_dma_eop\n");
396 }
397
398 void
si_dma_stop(struct ncr5380_softc * ncr_sc)399 si_dma_stop(struct ncr5380_softc *ncr_sc)
400 {
401 struct si_softc *sc = (struct si_softc *)ncr_sc;
402 struct sci_req *sr = ncr_sc->sc_current;
403 struct si_dma_handle *dh = sr->sr_dma_hand;
404 int count, i;
405
406 if (ncr_sc->sc_state & NCR_DOINGDMA)
407 ncr_sc->sc_state &= ~NCR_DOINGDMA;
408
409 /*
410 * Sometimes the FIFO buffer isn't drained when the
411 * interrupt is posted. Just loop here and hope that
412 * it will drain soon.
413 */
414 for (i = 0; i < 20000; i++) {
415 count = bus_space_read_4(ncr_sc->sc_regt,
416 ncr_sc->sc_regh, sc->ncr_dmacount);
417 if (count == 0)
418 break;
419 DELAY(100);
420 }
421 if (count == 0) {
422 if (((dh->dh_flags & SIDH_OUT) == 0)) {
423 vsbus_copytoproc(dh->dh_proc,
424 (char *)sc->ncr_addr + sc->ncr_off,
425 dh->dh_addr, dh->dh_len);
426 }
427 ncr_sc->sc_dataptr += dh->dh_len;
428 ncr_sc->sc_datalen -= dh->dh_len;
429 }
430
431 NCR5380_WRITE(ncr_sc, sci_mode, NCR5380_READ(ncr_sc, sci_mode) &
432 ~(SCI_MODE_DMA | SCI_MODE_DMA_IE));
433 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
434 if (sc->onlyscsi == 0)
435 vsbus_dma_intr(); /* Try to start more transfers */
436 }
437