1 /* $NetBSD: si.c,v 1.25 2024/02/13 05:35:13 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 1996,2000 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, Jason R. Thorpe and
9 * Paul Kranenburg.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * This file contains VME bus-dependent of the `si' SCSI adapter.
35 * This hardware is frequently found on Sun 3 and Sun 4 machines.
36 *
37 * The SCSI machinery on this adapter is implemented by an NCR5380,
38 * which is taken care of by the chipset driver in /sys/dev/ic/ncr5380sbc.c
39 *
40 * The logic has a bit to enable or disable the DMA engine,
41 * but that bit also gates the interrupt line from the NCR5380!
42 * Therefore, in order to get any interrupt from the 5380, (i.e.
43 * for reselect) one must clear the DMA engine transfer count and
44 * then enable DMA. This has the further complication that you
45 * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
46 * we have to turn DMA back off before we even look at the 5380.
47 *
48 * What wonderfully whacky hardware this is!
49 *
50 */
51
52 /*
53 * This driver originated as an MD implementation for the sun3 and sun4
54 * ports. The notes pertaining to that history are included below.
55 *
56 * David Jones wrote the initial version of this module for NetBSD/sun3,
57 * which included support for the VME adapter only. (no reselection).
58 *
59 * Gordon Ross added support for the Sun 3 OBIO adapter, and re-worked
60 * both the VME and OBIO code to support disconnect/reselect.
61 * (Required figuring out the hardware "features" noted above.)
62 *
63 * The autoconfiguration boilerplate came from Adam Glass.
64 *
65 * Jason R. Thorpe ported the autoconfiguration and VME portions to
66 * NetBSD/sparc, and added initial support for the 4/100 "SCSI Weird",
67 * a wacky OBIO variant of the VME SCSI-3. Many thanks to Chuck Cranor
68 * for lots of helpful tips and suggestions. Thanks also to Paul Kranenburg
69 * and Chris Torek for bits of insight needed along the way. Thanks to
70 * David Gilbert and Andrew Gillham who risked filesystem life-and-limb
71 * for the sake of testing. Andrew Gillham helped work out the bugs
72 * the 4/100 DMA code.
73 */
74
75 #include <sys/cdefs.h>
76 __KERNEL_RCSID(0, "$NetBSD: si.c,v 1.25 2024/02/13 05:35:13 thorpej Exp $");
77
78 #include "opt_ddb.h"
79
80 #include <sys/param.h>
81 #include <sys/systm.h>
82 #include <sys/kernel.h>
83 #include <sys/malloc.h>
84 #include <sys/errno.h>
85 #include <sys/device.h>
86 #include <sys/buf.h>
87
88 #include <sys/bus.h>
89 #include <sys/intr.h>
90
91 #include <dev/vme/vmereg.h>
92 #include <dev/vme/vmevar.h>
93
94 #include <dev/scsipi/scsi_all.h>
95 #include <dev/scsipi/scsipi_all.h>
96 #include <dev/scsipi/scsipi_debug.h>
97 #include <dev/scsipi/scsiconf.h>
98
99 #ifndef Debugger
100 #define Debugger()
101 #endif
102
103 #ifndef DEBUG
104 #define DEBUG XXX
105 #endif
106
107 #include <dev/ic/ncr5380reg.h>
108 #include <dev/ic/ncr5380var.h>
109
110 #include <dev/sun/sireg.h>
111
112 /*
113 * Transfers smaller than this are done using PIO
114 * (on assumption they're not worth DMA overhead)
115 */
116 #define MIN_DMA_LEN 128
117
118 #ifdef DEBUG
119 int si_debug = 0;
120 #endif
121
122 /*
123 * This structure is used to keep track of mapped DMA requests.
124 */
125 struct si_dma_handle {
126 int dh_flags;
127 #define SIDH_BUSY 0x01 /* This DH is in use */
128 #define SIDH_OUT 0x02 /* DMA does data out (write) */
129 int dh_maplen; /* Original data length */
130 bus_dmamap_t dh_dmamap;
131 #define dh_dvma dh_dmamap->dm_segs[0].ds_addr /* VA of buffer in DVMA space */
132 };
133
134 /*
135 * The first structure member has to be the ncr5380_softc
136 * so we can just cast to go back and fourth between them.
137 */
138 struct si_softc {
139 struct ncr5380_softc ncr_sc;
140 bus_space_tag_t sc_bustag; /* bus tags */
141 bus_dma_tag_t sc_dmatag;
142 vme_chipset_tag_t sc_vctag;
143
144 int sc_adapter_iv_am; /* int. vec + address modifier */
145 struct si_dma_handle *sc_dma;
146 int sc_xlen; /* length of current DMA segment. */
147 int sc_options; /* options for this instance. */
148 };
149
150 /*
151 * Options. By default, DMA is enabled and DMA completion interrupts
152 * and reselect are disabled. You may enable additional features
153 * the `flags' directive in your kernel's configuration file.
154 *
155 * Alternatively, you can patch your kernel with DDB or some other
156 * mechanism. The sc_options member of the softc is OR'd with
157 * the value in si_options.
158 *
159 * Note, there's a separate sw_options to make life easier.
160 */
161 #define SI_ENABLE_DMA 0x01 /* Use DMA (maybe polled) */
162 #define SI_DMA_INTR 0x02 /* DMA completion interrupts */
163 #define SI_DO_RESELECT 0x04 /* Allow disconnect/reselect */
164 #define SI_OPTIONS_MASK (SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT)
165 #define SI_OPTIONS_BITS "\10\3RESELECT\2DMA_INTR\1DMA"
166 int si_options = SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT;
167
168 static int si_match(device_t, cfdata_t, void *);
169 static void si_attach(device_t, device_t, void *);
170 static int si_intr(void *);
171 static void si_reset_adapter(struct ncr5380_softc *);
172
173 void si_dma_alloc(struct ncr5380_softc *);
174 void si_dma_free(struct ncr5380_softc *);
175 void si_dma_poll(struct ncr5380_softc *);
176
177 void si_dma_setup(struct ncr5380_softc *);
178 void si_dma_start(struct ncr5380_softc *);
179 void si_dma_eop(struct ncr5380_softc *);
180 void si_dma_stop(struct ncr5380_softc *);
181
182 void si_intr_on (struct ncr5380_softc *);
183 void si_intr_off(struct ncr5380_softc *);
184
185 /*
186 * Shorthand bus space access
187 * XXX - must look into endian issues here.
188 */
189 #define SIREG_READ(sc, index) \
190 bus_space_read_2((sc)->sc_regt, (sc)->sc_regh, index)
191 #define SIREG_WRITE(sc, index, v) \
192 bus_space_write_2((sc)->sc_regt, (sc)->sc_regh, index, v)
193
194
195 /* Auto-configuration glue. */
196 CFATTACH_DECL_NEW(si, sizeof(struct si_softc),
197 si_match, si_attach, NULL, NULL);
198
199 static int
si_match(device_t parent,cfdata_t cf,void * aux)200 si_match(device_t parent, cfdata_t cf, void *aux)
201 {
202 struct vme_attach_args *va = aux;
203 vme_chipset_tag_t ct = va->va_vct;
204 vme_am_t mod;
205 vme_addr_t vme_addr;
206
207 /* Make sure there is something there... */
208 mod = VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA;
209 vme_addr = va->r[0].offset;
210
211 if (vme_probe(ct, vme_addr, 1, mod, VME_D8, NULL, 0) != 0)
212 return 0;
213
214 /*
215 * If this is a VME SCSI board, we have to determine whether
216 * it is an "sc" (Sun2) or "si" (Sun3) SCSI board. This can
217 * be determined using the fact that the "sc" board occupies
218 * 4K bytes in VME space but the "si" board occupies 2K bytes.
219 */
220 return vme_probe(ct, vme_addr + 0x801, 1, mod, VME_D8, NULL, 0) != 0;
221 }
222
223 static void
si_attach(device_t parent,device_t self,void * aux)224 si_attach(device_t parent, device_t self, void *aux)
225 {
226 struct si_softc *sc = device_private(self);
227 struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
228 struct vme_attach_args *va = aux;
229 vme_chipset_tag_t ct = va->va_vct;
230 bus_space_tag_t bt;
231 bus_space_handle_t bh;
232 vme_mapresc_t resc;
233 vme_intr_handle_t ih;
234 vme_am_t mod;
235 char bits[64];
236 int i;
237
238 ncr_sc->sc_dev = self;
239 sc->sc_dmatag = va->va_bdt;
240 sc->sc_vctag = ct;
241
242 mod = VME_AM_A24 | VME_AM_MBO | VME_AM_SUPER | VME_AM_DATA;
243
244 if (vme_space_map(ct, va->r[0].offset, SIREG_BANK_SZ,
245 mod, VME_D8, 0, &bt, &bh, &resc) != 0)
246 panic("%s: vme_space_map", device_xname(self));
247
248 ncr_sc->sc_regt = bt;
249 ncr_sc->sc_regh = bh;
250
251 sc->sc_options = si_options;
252
253 ncr_sc->sc_dma_setup = si_dma_setup;
254 ncr_sc->sc_dma_start = si_dma_start;
255 ncr_sc->sc_dma_eop = si_dma_stop;
256 ncr_sc->sc_dma_stop = si_dma_stop;
257
258 vme_intr_map(ct, va->ilevel, va->ivector, &ih);
259 vme_intr_establish(ct, ih, IPL_BIO, si_intr, sc);
260
261 aprint_normal("\n");
262
263 sc->sc_adapter_iv_am = (mod << 8) | (va->ivector & 0xFF);
264
265 /*
266 * Pull in the options flags. Allow the user to completely
267 * override the default values.
268 */
269 if ((device_cfdata(self)->cf_flags & SI_OPTIONS_MASK) != 0)
270 sc->sc_options =
271 device_cfdata(self)->cf_flags & SI_OPTIONS_MASK;
272
273 /*
274 * Initialize fields used by the MI code
275 */
276
277 /* NCR5380 register bank offsets */
278 ncr_sc->sci_r0 = 0;
279 ncr_sc->sci_r1 = 1;
280 ncr_sc->sci_r2 = 2;
281 ncr_sc->sci_r3 = 3;
282 ncr_sc->sci_r4 = 4;
283 ncr_sc->sci_r5 = 5;
284 ncr_sc->sci_r6 = 6;
285 ncr_sc->sci_r7 = 7;
286
287 ncr_sc->sc_rev = NCR_VARIANT_NCR5380;
288
289 /*
290 * MD function pointers used by the MI code.
291 */
292 ncr_sc->sc_pio_out = ncr5380_pio_out;
293 ncr_sc->sc_pio_in = ncr5380_pio_in;
294 ncr_sc->sc_dma_alloc = si_dma_alloc;
295 ncr_sc->sc_dma_free = si_dma_free;
296 ncr_sc->sc_dma_poll = si_dma_poll;
297
298 ncr_sc->sc_flags = 0;
299 if ((sc->sc_options & SI_DO_RESELECT) == 0)
300 ncr_sc->sc_no_disconnect = 0xFF;
301 if ((sc->sc_options & SI_DMA_INTR) == 0)
302 ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
303 ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
304
305 /*
306 * Allocate DMA handles.
307 */
308 i = SCI_OPENINGS * sizeof(struct si_dma_handle);
309 sc->sc_dma = malloc(i, M_DEVBUF, M_WAITOK);
310 for (i = 0; i < SCI_OPENINGS; i++) {
311 sc->sc_dma[i].dh_flags = 0;
312
313 /* Allocate a DMA handle */
314 if (vme_dmamap_create(
315 sc->sc_vctag, /* VME chip tag */
316 MAXPHYS, /* size */
317 VME_AM_A24, /* address modifier */
318 VME_D16, /* data size */
319 0, /* swap */
320 1, /* nsegments */
321 MAXPHYS, /* maxsegsz */
322 0, /* boundary */
323 BUS_DMA_NOWAIT,
324 &sc->sc_dma[i].dh_dmamap) != 0) {
325
326 aprint_error_dev(self, "DMA buffer map create error\n");
327 return;
328 }
329 }
330
331 if (sc->sc_options) {
332 snprintb(bits, sizeof(bits), SI_OPTIONS_BITS, sc->sc_options);
333 aprint_normal_dev(self, "options=%s\n", bits);
334 }
335
336 ncr_sc->sc_channel.chan_id = 7;
337 ncr_sc->sc_adapter.adapt_minphys = minphys;
338
339 /*
340 * Initialize si board itself.
341 */
342 si_reset_adapter(ncr_sc);
343 ncr5380_attach(ncr_sc);
344
345 if (sc->sc_options & SI_DO_RESELECT) {
346 /*
347 * Need to enable interrupts (and DMA!)
348 * on this H/W for reselect to work.
349 */
350 ncr_sc->sc_intr_on = si_intr_on;
351 ncr_sc->sc_intr_off = si_intr_off;
352 }
353 }
354
355 #define CSR_WANT (SI_CSR_SBC_IP | SI_CSR_DMA_IP | \
356 SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR )
357
358 static int
si_intr(void * arg)359 si_intr(void *arg)
360 {
361 struct si_softc *sc = arg;
362 struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
363 int dma_error, claimed;
364 uint16_t csr;
365
366 claimed = 0;
367 dma_error = 0;
368
369 /* SBC interrupt? DMA interrupt? */
370 csr = SIREG_READ(ncr_sc, SIREG_CSR);
371
372 NCR_TRACE("si_intr: csr=0x%x\n", csr);
373
374 if (csr & SI_CSR_DMA_CONFLICT) {
375 dma_error |= SI_CSR_DMA_CONFLICT;
376 printf("%s: DMA conflict\n", __func__);
377 }
378 if (csr & SI_CSR_DMA_BUS_ERR) {
379 dma_error |= SI_CSR_DMA_BUS_ERR;
380 printf("%s: DMA bus error\n", __func__);
381 }
382 if (dma_error) {
383 if (sc->ncr_sc.sc_state & NCR_DOINGDMA)
384 sc->ncr_sc.sc_state |= NCR_ABORTING;
385 /* Make sure we will call the main isr. */
386 csr |= SI_CSR_DMA_IP;
387 }
388
389 if (csr & (SI_CSR_SBC_IP | SI_CSR_DMA_IP)) {
390 claimed = ncr5380_intr(&sc->ncr_sc);
391 #ifdef DEBUG
392 if (!claimed) {
393 printf("%s: spurious from SBC\n", __func__);
394 if (si_debug & 4) {
395 Debugger(); /* XXX */
396 }
397 }
398 #endif
399 }
400
401 return claimed;
402 }
403
404
405 static void
si_reset_adapter(struct ncr5380_softc * ncr_sc)406 si_reset_adapter(struct ncr5380_softc *ncr_sc)
407 {
408 struct si_softc *sc = (struct si_softc *)ncr_sc;
409
410 #ifdef DEBUG
411 if (si_debug) {
412 printf("%s\n", __func__);
413 }
414 #endif
415
416 /*
417 * The SCSI3 controller has an 8K FIFO to buffer data between the
418 * 5380 and the DMA. Make sure it starts out empty.
419 *
420 * The reset bits in the CSR are active low.
421 */
422 SIREG_WRITE(ncr_sc, SIREG_CSR, 0);
423 delay(10);
424 SIREG_WRITE(ncr_sc, SIREG_CSR,
425 SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN);
426 delay(10);
427
428 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
429 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
430 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
431 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
432 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
433 SIREG_WRITE(ncr_sc, SIREG_IV_AM, sc->sc_adapter_iv_am);
434 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
435
436 SCI_CLR_INTR(ncr_sc);
437 }
438
439 /*****************************************************************
440 * Common functions for DMA
441 ****************************************************************/
442
443 /*
444 * Allocate a DMA handle and put it in sc->sc_dma. Prepare
445 * for DMA transfer.
446 */
447 void
si_dma_alloc(struct ncr5380_softc * ncr_sc)448 si_dma_alloc(struct ncr5380_softc *ncr_sc)
449 {
450 struct si_softc *sc = (struct si_softc *)ncr_sc;
451 struct sci_req *sr = ncr_sc->sc_current;
452 struct scsipi_xfer *xs = sr->sr_xs;
453 struct si_dma_handle *dh;
454 int i, xlen;
455 u_long addr;
456
457 #ifdef DIAGNOSTIC
458 if (sr->sr_dma_hand != NULL)
459 panic("%s: already have DMA handle", __func__);
460 #endif
461
462 #if 1 /* XXX - Temporary */
463 /* XXX - In case we think DMA is completely broken... */
464 if ((sc->sc_options & SI_ENABLE_DMA) == 0)
465 return;
466 #endif
467
468 addr = (u_long)ncr_sc->sc_dataptr;
469 xlen = ncr_sc->sc_datalen;
470
471 /* If the DMA start addr is misaligned then do PIO */
472 if ((addr & 1) || (xlen & 1)) {
473 printf("%s: misaligned.\n", __func__);
474 return;
475 }
476
477 /* Make sure our caller checked sc_min_dma_len. */
478 if (xlen < MIN_DMA_LEN)
479 panic("%s: xlen=0x%x", __func__, xlen);
480
481 /* Find free DMA handle. Guaranteed to find one since we have
482 as many DMA handles as the driver has processes. */
483 for (i = 0; i < SCI_OPENINGS; i++) {
484 if ((sc->sc_dma[i].dh_flags & SIDH_BUSY) == 0)
485 goto found;
486 }
487 panic("si: no free DMA handles.");
488
489 found:
490 dh = &sc->sc_dma[i];
491 dh->dh_flags = SIDH_BUSY;
492 dh->dh_maplen = xlen;
493
494 /* Copy the "write" flag for convenience. */
495 if ((xs->xs_control & XS_CTL_DATA_OUT) != 0)
496 dh->dh_flags |= SIDH_OUT;
497
498 /*
499 * Double-map the buffer into DVMA space. If we can't re-map
500 * the buffer, we print a warning and fall back to PIO mode.
501 *
502 * NOTE: it is not safe to sleep here!
503 */
504 if (bus_dmamap_load(sc->sc_dmatag, dh->dh_dmamap,
505 (void *)addr, xlen, NULL, BUS_DMA_NOWAIT) != 0) {
506 /* Can't remap segment */
507 printf("%s: can't remap 0x%lx/0x%x, doing PIO\n",
508 __func__, addr, dh->dh_maplen);
509 dh->dh_flags = 0;
510 return;
511 }
512 bus_dmamap_sync(sc->sc_dmatag, dh->dh_dmamap, addr, xlen,
513 (dh->dh_flags & SIDH_OUT)
514 ? BUS_DMASYNC_PREWRITE
515 : BUS_DMASYNC_PREREAD);
516
517 /* success */
518 sr->sr_dma_hand = dh;
519 }
520
521
522 void
si_dma_free(struct ncr5380_softc * ncr_sc)523 si_dma_free(struct ncr5380_softc *ncr_sc)
524 {
525 struct si_softc *sc = (struct si_softc *)ncr_sc;
526 struct sci_req *sr = ncr_sc->sc_current;
527 struct si_dma_handle *dh = sr->sr_dma_hand;
528
529 #ifdef DIAGNOSTIC
530 if (dh == NULL)
531 panic("%s: no DMA handle", __func__);
532 #endif
533
534 if (ncr_sc->sc_state & NCR_DOINGDMA)
535 panic("%s: free while in progress", __func__);
536
537 if (dh->dh_flags & SIDH_BUSY) {
538 /* Give back the DVMA space. */
539 bus_dmamap_sync(sc->sc_dmatag, dh->dh_dmamap,
540 dh->dh_dvma, dh->dh_maplen,
541 (dh->dh_flags & SIDH_OUT)
542 ? BUS_DMASYNC_POSTWRITE
543 : BUS_DMASYNC_POSTREAD);
544 bus_dmamap_unload(sc->sc_dmatag, dh->dh_dmamap);
545 dh->dh_flags = 0;
546 }
547 sr->sr_dma_hand = NULL;
548 }
549
550
551 /*
552 * Poll (spin-wait) for DMA completion.
553 * Called right after xx_dma_start(), and
554 * xx_dma_stop() will be called next.
555 * Same for either VME or OBIO.
556 */
557 void
si_dma_poll(struct ncr5380_softc * ncr_sc)558 si_dma_poll(struct ncr5380_softc *ncr_sc)
559 {
560 struct sci_req *sr = ncr_sc->sc_current;
561 int tmo, csr_mask, csr;
562
563 /* Make sure DMA started successfully. */
564 if (ncr_sc->sc_state & NCR_ABORTING)
565 return;
566
567 csr_mask = SI_CSR_SBC_IP | SI_CSR_DMA_IP |
568 SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR;
569
570 tmo = 50000; /* X100 = 5 sec. */
571 for (;;) {
572 csr = SIREG_READ(ncr_sc, SIREG_CSR);
573 if (csr & csr_mask)
574 break;
575 if (--tmo <= 0) {
576 printf("%s: DMA timeout (while polling)\n",
577 device_xname(ncr_sc->sc_dev));
578 /* Indicate timeout as MI code would. */
579 sr->sr_flags |= SR_OVERDUE;
580 break;
581 }
582 delay(100);
583 }
584
585 #ifdef DEBUG
586 if (si_debug) {
587 printf("%s: done, csr=0x%x\n", __func__, csr);
588 }
589 #endif
590 }
591
592
593 /*****************************************************************
594 * VME functions for DMA
595 ****************************************************************/
596
597
598 /*
599 * This is called when the bus is going idle,
600 * so we want to enable the SBC interrupts.
601 * That is controlled by the DMA enable!
602 * Who would have guessed!
603 * What a NASTY trick!
604 */
605 void
si_intr_on(struct ncr5380_softc * ncr_sc)606 si_intr_on(struct ncr5380_softc *ncr_sc)
607 {
608 uint16_t csr;
609
610 /* Clear DMA start address and counters */
611 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
612 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
613 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
614 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
615
616 /* Enter receive mode (for safety) and enable DMA engine */
617 csr = SIREG_READ(ncr_sc, SIREG_CSR);
618 csr &= ~SI_CSR_SEND;
619 csr |= SI_CSR_DMA_EN;
620 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
621 }
622
623 /*
624 * This is called when the bus is idle and we are
625 * about to start playing with the SBC chip.
626 */
627 void
si_intr_off(struct ncr5380_softc * ncr_sc)628 si_intr_off(struct ncr5380_softc *ncr_sc)
629 {
630 uint16_t csr;
631
632 csr = SIREG_READ(ncr_sc, SIREG_CSR);
633 csr &= ~SI_CSR_DMA_EN;
634 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
635 }
636
637 /*
638 * This function is called during the COMMAND or MSG_IN phase
639 * that precedes a DATA_IN or DATA_OUT phase, in case we need
640 * to setup the DMA engine before the bus enters a DATA phase.
641 *
642 * XXX: The VME adapter appears to suppress SBC interrupts
643 * when the FIFO is not empty or the FIFO count is non-zero!
644 *
645 * On the VME version we just clear the DMA count and address
646 * here (to make sure it stays idle) and do the real setup
647 * later, in dma_start.
648 */
649 void
si_dma_setup(struct ncr5380_softc * ncr_sc)650 si_dma_setup(struct ncr5380_softc *ncr_sc)
651 {
652 struct si_softc *sc = (struct si_softc *)ncr_sc;
653 struct sci_req *sr = ncr_sc->sc_current;
654 struct si_dma_handle *dh = sr->sr_dma_hand;
655 uint16_t csr;
656 u_long dva;
657 int xlen;
658
659 /*
660 * Set up the DMA controller.
661 * Note that (dh->dh_len < sc_datalen)
662 */
663
664 csr = SIREG_READ(ncr_sc, SIREG_CSR);
665
666 /* Disable DMA while we're setting up the transfer */
667 csr &= ~SI_CSR_DMA_EN;
668
669 /* Reset the FIFO */
670 csr &= ~SI_CSR_FIFO_RES; /* active low */
671 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
672 csr |= SI_CSR_FIFO_RES;
673 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
674
675 /*
676 * Get the DVMA mapping for this segment.
677 */
678 dva = (u_long)(dh->dh_dvma);
679 if (dva & 1)
680 panic("%s: bad dmaaddr=0x%lx", __func__, dva);
681 xlen = ncr_sc->sc_datalen;
682 xlen &= ~1;
683 sc->sc_xlen = xlen; /* XXX: or less... */
684
685 #ifdef DEBUG
686 if (si_debug & 2) {
687 printf("%s: dh=%p, dmaaddr=0x%lx, xlen=%d\n",
688 __func__, dh, dva, xlen);
689 }
690 #endif
691 /* Set direction (send/recv) */
692 if (dh->dh_flags & SIDH_OUT) {
693 csr |= SI_CSR_SEND;
694 } else {
695 csr &= ~SI_CSR_SEND;
696 }
697
698 /* Set byte-packing control */
699 if (dva & 2) {
700 csr |= SI_CSR_BPCON;
701 } else {
702 csr &= ~SI_CSR_BPCON;
703 }
704
705 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
706
707 /* Load start address */
708 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, (uint16_t)(dva >> 16));
709 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, (uint16_t)(dva & 0xFFFF));
710
711 /* Clear DMA counters; these will be set in si_dma_start() */
712 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
713 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
714
715 /* Clear FIFO counter. (also hits dma_count) */
716 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
717 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
718 }
719
720
721 void
si_dma_start(struct ncr5380_softc * ncr_sc)722 si_dma_start(struct ncr5380_softc *ncr_sc)
723 {
724 struct si_softc *sc = (struct si_softc *)ncr_sc;
725 struct sci_req *sr = ncr_sc->sc_current;
726 struct si_dma_handle *dh = sr->sr_dma_hand;
727 int xlen;
728 u_int mode;
729 uint16_t csr;
730
731 xlen = sc->sc_xlen;
732
733 /* Load transfer length */
734 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, (uint16_t)(xlen >> 16));
735 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, (uint16_t)(xlen & 0xFFFF));
736 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, (uint16_t)(xlen >> 16));
737 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, (uint16_t)(xlen & 0xFFFF));
738
739 /*
740 * Acknowledge the phase change. (After DMA setup!)
741 * Put the SBIC into DMA mode, and start the transfer.
742 */
743 if (dh->dh_flags & SIDH_OUT) {
744 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_OUT);
745 SCI_CLR_INTR(ncr_sc);
746 NCR5380_WRITE(ncr_sc, sci_icmd, SCI_ICMD_DATA);
747
748 mode = NCR5380_READ(ncr_sc, sci_mode);
749 mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
750 NCR5380_WRITE(ncr_sc, sci_mode, mode);
751
752 NCR5380_WRITE(ncr_sc, sci_dma_send, 0); /* start it */
753 } else {
754 NCR5380_WRITE(ncr_sc, sci_tcmd, PHASE_DATA_IN);
755 SCI_CLR_INTR(ncr_sc);
756 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
757
758 mode = NCR5380_READ(ncr_sc, sci_mode);
759 mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
760 NCR5380_WRITE(ncr_sc, sci_mode, mode);
761
762 NCR5380_WRITE(ncr_sc, sci_irecv, 0); /* start it */
763 }
764
765 ncr_sc->sc_state |= NCR_DOINGDMA;
766
767 /* Enable DMA engine */
768 csr = SIREG_READ(ncr_sc, SIREG_CSR);
769 csr |= SI_CSR_DMA_EN;
770 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
771
772 #ifdef DEBUG
773 if (si_debug & 2) {
774 printf("%s: started, flags=0x%x\n",
775 __func__, ncr_sc->sc_state);
776 }
777 #endif
778 }
779
780
781 void
si_dma_eop(struct ncr5380_softc * ncr_sc)782 si_dma_eop(struct ncr5380_softc *ncr_sc)
783 {
784
785 /* Not needed - DMA was stopped prior to examining sci_csr */
786 }
787
788
789 void
si_dma_stop(struct ncr5380_softc * ncr_sc)790 si_dma_stop(struct ncr5380_softc *ncr_sc)
791 {
792 struct si_softc *sc = (struct si_softc *)ncr_sc;
793 struct sci_req *sr = ncr_sc->sc_current;
794 struct si_dma_handle *dh = sr->sr_dma_hand;
795 int resid, ntrans;
796 uint16_t csr;
797 u_int mode;
798
799 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
800 #ifdef DEBUG
801 printf("%s: DMA not running\n", __func__);
802 #endif
803 return;
804 }
805
806 ncr_sc->sc_state &= ~NCR_DOINGDMA;
807
808 csr = SIREG_READ(ncr_sc, SIREG_CSR);
809
810 /* First, halt the DMA engine. */
811 csr &= ~SI_CSR_DMA_EN;
812 SIREG_WRITE(ncr_sc, SIREG_CSR, csr);
813
814 if (csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
815 printf("si: DMA error, csr=0x%x, reset\n", csr);
816 sr->sr_xs->error = XS_DRIVER_STUFFUP;
817 ncr_sc->sc_state |= NCR_ABORTING;
818 si_reset_adapter(ncr_sc);
819 }
820
821 /* Note that timeout may have set the error flag. */
822 if (ncr_sc->sc_state & NCR_ABORTING)
823 goto out;
824
825 /*
826 * Now try to figure out how much actually transferred
827 *
828 * The fifo_count does not reflect how many bytes were
829 * actually transferred for VME.
830 *
831 * SCSI-3 VME interface is a little funny on writes:
832 * if we have a disconnect, the DMA has overshot by
833 * one byte and the resid needs to be incremented.
834 * Only happens for partial transfers.
835 * (Thanks to Matt Jacob)
836 */
837
838 resid = SIREG_READ(ncr_sc, SIREG_FIFO_CNTH) << 16;
839 resid |= SIREG_READ(ncr_sc, SIREG_FIFO_CNT) & 0xFFFF;
840 if (dh->dh_flags & SIDH_OUT)
841 if ((resid > 0) && (resid < sc->sc_xlen))
842 resid++;
843 ntrans = sc->sc_xlen - resid;
844
845 #ifdef DEBUG
846 if (si_debug & 2) {
847 printf("%s: resid=0x%x ntrans=0x%x\n",
848 __func__, resid, ntrans);
849 }
850 #endif
851
852 if (ntrans > ncr_sc->sc_datalen)
853 panic("%s: excess transfer", __func__);
854
855 /* Adjust data pointer */
856 ncr_sc->sc_dataptr += ntrans;
857 ncr_sc->sc_datalen -= ntrans;
858
859 #ifdef DEBUG
860 if (si_debug & 2) {
861 printf("%s: ntrans=0x%x\n", __func__, ntrans);
862 }
863 #endif
864
865 /*
866 * After a read, we may need to clean-up
867 * "Left-over bytes" (yuck!)
868 */
869 if (((dh->dh_flags & SIDH_OUT) == 0) &&
870 ((csr & SI_CSR_LOB) != 0)) {
871 uint8_t *cp = ncr_sc->sc_dataptr;
872 uint16_t bprh, bprl;
873
874 bprh = SIREG_READ(ncr_sc, SIREG_BPRH);
875 bprl = SIREG_READ(ncr_sc, SIREG_BPRL);
876
877 #ifdef DEBUG
878 printf("si: got left-over bytes: bprh=%x, bprl=%x, csr=%x\n",
879 bprh, bprl, csr);
880 #endif
881
882 if (csr & SI_CSR_BPCON) {
883 /* have SI_CSR_BPCON */
884 cp[-1] = (bprl & 0xff00) >> 8;
885 } else {
886 switch (csr & SI_CSR_LOB) {
887 case SI_CSR_LOB_THREE:
888 cp[-3] = (bprh & 0xff00) >> 8;
889 cp[-2] = (bprh & 0x00ff);
890 cp[-1] = (bprl & 0xff00) >> 8;
891 break;
892 case SI_CSR_LOB_TWO:
893 cp[-2] = (bprh & 0xff00) >> 8;
894 cp[-1] = (bprh & 0x00ff);
895 break;
896 case SI_CSR_LOB_ONE:
897 cp[-1] = (bprh & 0xff00) >> 8;
898 break;
899 }
900 }
901 }
902
903 out:
904 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRH, 0);
905 SIREG_WRITE(ncr_sc, SIREG_DMA_ADDRL, 0);
906
907 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTH, 0);
908 SIREG_WRITE(ncr_sc, SIREG_DMA_CNTL, 0);
909
910 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNTH, 0);
911 SIREG_WRITE(ncr_sc, SIREG_FIFO_CNT, 0);
912
913 mode = NCR5380_READ(ncr_sc, sci_mode);
914 /* Put SBIC back in PIO mode. */
915 mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
916 NCR5380_WRITE(ncr_sc, sci_mode, mode);
917 NCR5380_WRITE(ncr_sc, sci_icmd, 0);
918 }
919