si_obio.c revision 1.6 1 /* $NetBSD: si_obio.c,v 1.6 1996/10/30 00:31:39 gwr Exp $ */
2
3 /*
4 * Copyright (c) 1995 David Jones, Gordon W. Ross
5 * Copyright (c) 1994 Adam Glass
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the authors may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 * 4. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by
21 * Adam Glass, David Jones, and Gordon Ross
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * This file contains only the machine-dependent parts of the
37 * Sun3 SCSI driver. (Autoconfig stuff and DMA functions.)
38 * The machine-independent parts are in ncr5380sbc.c
39 *
40 * Supported hardware includes:
41 * Sun SCSI-3 on OBIO (Sun3/50,Sun3/60)
42 * Sun SCSI-3 on VME (Sun3/160,Sun3/260)
43 *
44 * Could be made to support the Sun3/E if someone wanted to.
45 *
46 * Note: Both supported variants of the Sun SCSI-3 adapter have
47 * some really unusual "features" for this driver to deal with,
48 * generally related to the DMA engine. The OBIO variant will
49 * ignore any attempt to write the FIFO count register while the
50 * SCSI bus is in DATA_IN or DATA_OUT phase. This is dealt with
51 * by setting the FIFO count early in COMMAND or MSG_IN phase.
52 *
53 * The VME variant has a bit to enable or disable the DMA engine,
54 * but that bit also gates the interrupt line from the NCR5380!
55 * Therefore, in order to get any interrupt from the 5380, (i.e.
56 * for reselect) one must clear the DMA engine transfer count and
57 * then enable DMA. This has the further complication that you
58 * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
59 * we have to turn DMA back off before we even look at the 5380.
60 *
61 * What wonderfully whacky hardware this is!
62 *
63 * Credits, history:
64 *
65 * David Jones wrote the initial version of this module, which
66 * included support for the VME adapter only. (no reselection).
67 *
68 * Gordon Ross added support for the OBIO adapter, and re-worked
69 * both the VME and OBIO code to support disconnect/reselect.
70 * (Required figuring out the hardware "features" noted above.)
71 *
72 * The autoconfiguration boilerplate came from Adam Glass.
73 */
74
75 /*****************************************************************
76 * OBIO functions for DMA
77 ****************************************************************/
78
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/errno.h>
82 #include <sys/kernel.h>
83 #include <sys/malloc.h>
84 #include <sys/device.h>
85 #include <sys/buf.h>
86 #include <sys/proc.h>
87 #include <sys/user.h>
88
89 #include <scsi/scsi_all.h>
90 #include <scsi/scsi_debug.h>
91 #include <scsi/scsiconf.h>
92
93 #include <machine/autoconf.h>
94 #include <machine/isr.h>
95 #include <machine/obio.h>
96 #include <machine/dvma.h>
97
98 #define DEBUG XXX
99
100 #include <dev/ic/ncr5380reg.h>
101 #include <dev/ic/ncr5380var.h>
102
103 #include "sireg.h"
104 #include "sivar.h"
105 #include "am9516.h"
106
107 /*
108 * How many uS. to delay after touching the am9516 UDC.
109 */
110 #define UDC_WAIT_USEC 5
111
112 void si_obio_dma_setup __P((struct ncr5380_softc *));
113 void si_obio_dma_start __P((struct ncr5380_softc *));
114 void si_obio_dma_eop __P((struct ncr5380_softc *));
115 void si_obio_dma_stop __P((struct ncr5380_softc *));
116
117 /*
118 * New-style autoconfig attachment
119 */
120
121 static int si_obio_match __P((struct device *, void *, void *));
122 static void si_obio_attach __P((struct device *, struct device *, void *));
123
124 struct cfattach si_obio_ca = {
125 sizeof(struct si_softc), si_obio_match, si_obio_attach
126 };
127
128 /* Options. Interesting values are: 1,3,7 */
129 /* XXX: Using 1 for now to mask a (pmap?) bug not yet found... */
130 int si_obio_options = 1; /* XXX */
131
132
133 static int
134 si_obio_match(parent, vcf, args)
135 struct device *parent;
136 void *vcf, *args;
137 {
138 struct cfdata *cf = vcf;
139 struct confargs *ca = args;
140
141 /* Make sure there is something there... */
142 if (bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1) == -1)
143 return (0);
144
145 /* Default interrupt priority. */
146 if (ca->ca_intpri == -1)
147 ca->ca_intpri = 2;
148
149 return (1);
150 }
151
152 static void
153 si_obio_attach(parent, self, args)
154 struct device *parent, *self;
155 void *args;
156 {
157 struct si_softc *sc = (struct si_softc *) self;
158 struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
159 struct cfdata *cf = self->dv_cfdata;
160 struct confargs *ca = args;
161
162 /* Get options from config flags... */
163 sc->sc_options = cf->cf_flags | si_obio_options;
164 printf(": options=%d\n", sc->sc_options);
165
166 sc->sc_adapter_type = ca->ca_bustype;
167 sc->sc_regs = (struct si_regs *)
168 obio_alloc(ca->ca_paddr, sizeof(struct si_regs));
169
170 /*
171 * MD function pointers used by the MI code.
172 */
173 ncr_sc->sc_pio_out = ncr5380_pio_out;
174 ncr_sc->sc_pio_in = ncr5380_pio_in;
175 ncr_sc->sc_dma_alloc = si_dma_alloc;
176 ncr_sc->sc_dma_free = si_dma_free;
177 ncr_sc->sc_dma_setup = si_obio_dma_setup;
178 ncr_sc->sc_dma_start = si_obio_dma_start;
179 ncr_sc->sc_dma_poll = si_dma_poll;
180 ncr_sc->sc_dma_eop = si_obio_dma_eop;
181 ncr_sc->sc_dma_stop = si_obio_dma_stop;
182 ncr_sc->sc_intr_on = NULL;
183 ncr_sc->sc_intr_off = NULL;
184
185 /* Need DVMA-capable memory for the UDC command block. */
186 sc->sc_dmacmd = dvma_malloc(sizeof (struct udc_table));
187
188 /* Attach interrupt handler. */
189 isr_add_autovect(si_intr, (void *)sc, ca->ca_intpri);
190
191 /* Do the common attach stuff. */
192 si_attach(sc);
193 }
194
195
196 static __inline__ void
197 si_obio_udc_write(si, regnum, value)
198 volatile struct si_regs *si;
199 int regnum, value;
200 {
201 si->udc_addr = regnum;
202 delay(UDC_WAIT_USEC);
203 si->udc_data = value;
204 delay(UDC_WAIT_USEC);
205 }
206
207 static __inline__ int
208 si_obio_udc_read(si, regnum)
209 volatile struct si_regs *si;
210 int regnum;
211 {
212 int value;
213
214 si->udc_addr = regnum;
215 delay(UDC_WAIT_USEC);
216 value = si->udc_data;
217 delay(UDC_WAIT_USEC);
218
219 return (value);
220 }
221
222
223 /*
224 * This function is called during the COMMAND or MSG_IN phase
225 * that preceeds a DATA_IN or DATA_OUT phase, in case we need
226 * to setup the DMA engine before the bus enters a DATA phase.
227 *
228 * The OBIO "si" IGNORES any attempt to set the FIFO count
229 * register after the SCSI bus goes into any DATA phase, so
230 * this function has to setup the evil FIFO logic.
231 */
232 void
233 si_obio_dma_setup(ncr_sc)
234 struct ncr5380_softc *ncr_sc;
235 {
236 struct si_softc *sc = (struct si_softc *)ncr_sc;
237 struct sci_req *sr = ncr_sc->sc_current;
238 struct si_dma_handle *dh = sr->sr_dma_hand;
239 volatile struct si_regs *si = sc->sc_regs;
240 struct udc_table *cmd;
241 long data_pa, cmd_pa;
242 int xlen;
243
244 /*
245 * Get the DVMA mapping for this segment.
246 * XXX - Should separate allocation and mapin.
247 */
248 data_pa = dvma_kvtopa(dh->dh_dvma, sc->sc_adapter_type);
249 data_pa += (ncr_sc->sc_dataptr - dh->dh_addr);
250 if (data_pa & 1)
251 panic("si_dma_start: bad pa=0x%x", data_pa);
252 xlen = ncr_sc->sc_datalen;
253 sc->sc_reqlen = xlen; /* XXX: or less? */
254
255 #ifdef DEBUG
256 if (si_debug & 2) {
257 printf("si_dma_setup: dh=0x%x, pa=0x%x, xlen=%d\n",
258 dh, data_pa, xlen);
259 }
260 #endif
261
262 /* Reset the UDC. (In case not already reset?) */
263 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
264
265 /* Reset the FIFO */
266 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
267 si->si_csr |= SI_CSR_FIFO_RES;
268
269 /* Set direction (send/recv) */
270 if (dh->dh_flags & SIDH_OUT) {
271 si->si_csr |= SI_CSR_SEND;
272 } else {
273 si->si_csr &= ~SI_CSR_SEND;
274 }
275
276 /* Set the FIFO counter. */
277 si->fifo_count = xlen;
278
279 /* Reset the UDC. */
280 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
281
282 /*
283 * XXX: Reset the FIFO again! Comment from Sprite:
284 * Go through reset again becuase of the bug on the 3/50
285 * where bytes occasionally linger in the DMA fifo.
286 */
287 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
288 si->si_csr |= SI_CSR_FIFO_RES;
289
290 #ifdef DEBUG
291 /* Make sure the extra FIFO reset did not hit the count. */
292 if (si->fifo_count != xlen) {
293 printf("si_dma_setup: fifo_count=0x%x, xlen=0x%x\n",
294 si->fifo_count, xlen);
295 Debugger();
296 }
297 #endif
298
299 /*
300 * Set up the DMA controller. The DMA controller on
301 * OBIO needs a command block in DVMA space.
302 */
303 cmd = sc->sc_dmacmd;
304 cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO;
305 cmd->addrl = data_pa & 0xFFFF;
306 cmd->count = xlen / 2; /* bytes -> words */
307 cmd->cmrh = UDC_CMR_HIGH;
308 if (dh->dh_flags & SIDH_OUT) {
309 if (xlen & 1)
310 cmd->count++;
311 cmd->cmrl = UDC_CMR_LSEND;
312 cmd->rsel = UDC_RSEL_SEND;
313 } else {
314 cmd->cmrl = UDC_CMR_LRECV;
315 cmd->rsel = UDC_RSEL_RECV;
316 }
317
318 /* Tell the DMA chip where the control block is. */
319 cmd_pa = dvma_kvtopa((long)cmd, BUS_OBIO);
320 si_obio_udc_write(si, UDC_ADR_CAR_HIGH,
321 (cmd_pa & 0xff0000) >> 8);
322 si_obio_udc_write(si, UDC_ADR_CAR_LOW,
323 (cmd_pa & 0xffff));
324
325 /* Tell the chip to be a DMA master. */
326 si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE);
327
328 /* Tell the chip to interrupt on error. */
329 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE);
330
331 /* Will do "start chain" command in _dma_start. */
332 }
333
334
335 void
336 si_obio_dma_start(ncr_sc)
337 struct ncr5380_softc *ncr_sc;
338 {
339 struct si_softc *sc = (struct si_softc *)ncr_sc;
340 struct sci_req *sr = ncr_sc->sc_current;
341 struct si_dma_handle *dh = sr->sr_dma_hand;
342 volatile struct si_regs *si = sc->sc_regs;
343 int s;
344
345 #ifdef DEBUG
346 if (si_debug & 2) {
347 printf("si_dma_start: sr=0x%x\n", sr);
348 }
349 #endif
350
351 /* This MAY be time critical (not sure). */
352 s = splhigh();
353
354 /* Finally, give the UDC a "start chain" command. */
355 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN);
356
357 /*
358 * Acknowledge the phase change. (After DMA setup!)
359 * Put the SBIC into DMA mode, and start the transfer.
360 */
361 if (dh->dh_flags & SIDH_OUT) {
362 *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
363 SCI_CLR_INTR(ncr_sc);
364 *ncr_sc->sci_icmd = SCI_ICMD_DATA;
365 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
366 *ncr_sc->sci_dma_send = 0; /* start it */
367 } else {
368 *ncr_sc->sci_tcmd = PHASE_DATA_IN;
369 SCI_CLR_INTR(ncr_sc);
370 *ncr_sc->sci_icmd = 0;
371 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
372 *ncr_sc->sci_irecv = 0; /* start it */
373 }
374
375 splx(s);
376 ncr_sc->sc_state |= NCR_DOINGDMA;
377
378 #ifdef DEBUG
379 if (si_debug & 2) {
380 printf("si_dma_start: started, flags=0x%x\n",
381 ncr_sc->sc_state);
382 }
383 #endif
384 }
385
386
387 void
388 si_obio_dma_eop(ncr_sc)
389 struct ncr5380_softc *ncr_sc;
390 {
391
392 /* Not needed - DMA was stopped prior to examining sci_csr */
393 }
394
395
396 void
397 si_obio_dma_stop(ncr_sc)
398 struct ncr5380_softc *ncr_sc;
399 {
400 struct si_softc *sc = (struct si_softc *)ncr_sc;
401 struct sci_req *sr = ncr_sc->sc_current;
402 struct si_dma_handle *dh = sr->sr_dma_hand;
403 volatile struct si_regs *si = sc->sc_regs;
404 int resid, ntrans, tmo, udc_cnt;
405
406 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
407 #ifdef DEBUG
408 printf("si_dma_stop: dma not running\n");
409 #endif
410 return;
411 }
412 ncr_sc->sc_state &= ~NCR_DOINGDMA;
413
414 NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr);
415
416 /* OK, have either phase mis-match or end of DMA. */
417 /* Set an impossible phase to prevent data movement? */
418 *ncr_sc->sci_tcmd = PHASE_INVALID;
419
420 /* Check for DMA errors. */
421 if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
422 printf("si: DMA error, csr=0x%x, reset\n", si->si_csr);
423 sr->sr_xs->error = XS_DRIVER_STUFFUP;
424 ncr_sc->sc_state |= NCR_ABORTING;
425 si_reset_adapter(ncr_sc);
426 goto out;
427 }
428
429 /* Note that timeout may have set the error flag. */
430 if (ncr_sc->sc_state & NCR_ABORTING)
431 goto out;
432
433 /*
434 * After a read, wait for the FIFO to empty.
435 * Note: this only works on the OBIO version.
436 */
437 if ((dh->dh_flags & SIDH_OUT) == 0) {
438 tmo = 200000; /* X10 = 2 sec. */
439 for (;;) {
440 if (si->si_csr & SI_CSR_FIFO_EMPTY)
441 break;
442 if (--tmo <= 0) {
443 printf("si: dma fifo did not empty, reset\n");
444 ncr_sc->sc_state |= NCR_ABORTING;
445 /* si_reset_adapter(ncr_sc); */
446 goto out;
447 }
448 delay(10);
449 }
450 }
451
452 /*
453 * Now try to figure out how much actually transferred
454 * The fifo_count might not reflect how many bytes were
455 * actually transferred.
456 */
457 resid = si->fifo_count & 0xFFFF;
458 ntrans = sc->sc_reqlen - resid;
459
460 #ifdef DEBUG
461 if (si_debug & 2) {
462 printf("si_dma_stop: resid=0x%x ntrans=0x%x\n",
463 resid, ntrans);
464 }
465 #endif
466
467 /* XXX: Treat (ntrans==0) as a special, non-error case? */
468 if (ntrans < MIN_DMA_LEN) {
469 printf("si: fifo count: 0x%x\n", resid);
470 ncr_sc->sc_state |= NCR_ABORTING;
471 goto out;
472 }
473 if (ntrans > ncr_sc->sc_datalen)
474 panic("si_dma_stop: excess transfer");
475
476 /* Adjust data pointer */
477 ncr_sc->sc_dataptr += ntrans;
478 ncr_sc->sc_datalen -= ntrans;
479
480 /*
481 * After a read, we may need to clean-up
482 * "Left-over bytes" (yuck!)
483 */
484 if ((dh->dh_flags & SIDH_OUT) == 0) {
485 /* If odd transfer count, grab last byte by hand. */
486 if (ntrans & 1) {
487 NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n",
488 (int) ncr_sc->sc_dataptr - 1);
489 ncr_sc->sc_dataptr[-1] =
490 (si->fifo_data & 0xff00) >> 8;
491 goto out;
492 }
493 /* UDC might not have transfered the last word. */
494 udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT);
495 if (((udc_cnt * 2) - resid) == 2) {
496 NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n",
497 (int) ncr_sc->sc_dataptr - 2);
498 ncr_sc->sc_dataptr[-2] =
499 (si->fifo_data & 0xff00) >> 8;
500 ncr_sc->sc_dataptr[-1] =
501 (si->fifo_data & 0x00ff);
502 }
503 }
504
505 out:
506 /* Reset the UDC. */
507 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
508 si->fifo_count = 0;
509 si->si_csr &= ~SI_CSR_SEND;
510
511 /* Reset the FIFO */
512 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
513 si->si_csr |= SI_CSR_FIFO_RES;
514
515 /* Put SBIC back in PIO mode. */
516 /* XXX: set tcmd to PHASE_INVALID? */
517 *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
518 *ncr_sc->sci_icmd = 0;
519 }
520
521