si_obio.c revision 1.4 1 /* $NetBSD: si_obio.c,v 1.4 1996/10/13 03:47:37 christos 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 #define SI_ENABLE_DMA 1 /* Use DMA (maybe polled) */
132 #define SI_DMA_INTR 2 /* DMA completion interrupts */
133 #define SI_DO_RESELECT 4 /* Allow disconnect/reselect */
134
135
136 static int
137 si_obio_match(parent, vcf, args)
138 struct device *parent;
139 void *vcf, *args;
140 {
141 struct cfdata *cf = vcf;
142 struct confargs *ca = args;
143 int pa, x;
144
145 #ifdef DIAGNOSTIC
146 if (ca->ca_bustype != BUS_OBIO) {
147 printf("si_obio_match: bustype %d?\n", ca->ca_bustype);
148 return (0);
149 }
150 #endif
151
152 /*
153 * OBIO match functions may be called for every possible
154 * physical address, so match only our physical address.
155 */
156 if ((pa = cf->cf_paddr) == -1) {
157 /* Use our default PA. */
158 pa = OBIO_NCR_SCSI;
159 }
160 if (pa != ca->ca_paddr)
161 return (0);
162
163 #if 0
164 if ((cpu_machine_id != SUN3_MACH_50) &&
165 (cpu_machine_id != SUN3_MACH_60) )
166 {
167 /* Only 3/50 and 3/60 have the obio si. */
168 return (0);
169 }
170 #endif
171
172 /* Make sure there is something there... */
173 x = bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1);
174 return (x != -1);
175 }
176
177 static void
178 si_obio_attach(parent, self, args)
179 struct device *parent, *self;
180 void *args;
181 {
182 struct si_softc *sc = (struct si_softc *) self;
183 struct ncr5380_softc *ncr_sc = &sc->ncr_sc;
184 struct cfdata *cf = self->dv_cfdata;
185 struct confargs *ca = args;
186 int intpri;
187
188 /* Default interrupt level. */
189 if ((intpri = cf->cf_intpri) == -1)
190 intpri = 2;
191 printf(" level %d", intpri);
192
193 /* XXX: Get options from flags... */
194 printf(" : options=%d\n", si_obio_options);
195
196 ncr_sc->sc_flags = 0;
197 if (si_obio_options & SI_DO_RESELECT)
198 ncr_sc->sc_flags |= NCR5380_PERMIT_RESELECT;
199 if ((si_obio_options & SI_DMA_INTR) == 0)
200 ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
201
202 sc->sc_adapter_type = ca->ca_bustype;
203 sc->sc_regs = (struct si_regs *)
204 obio_alloc(ca->ca_paddr, sizeof(struct si_regs));
205
206 /*
207 * MD function pointers used by the MI code.
208 */
209 ncr_sc->sc_pio_out = ncr5380_pio_out;
210 ncr_sc->sc_pio_in = ncr5380_pio_in;
211 ncr_sc->sc_dma_alloc = si_dma_alloc;
212 ncr_sc->sc_dma_free = si_dma_free;
213 ncr_sc->sc_dma_setup = si_obio_dma_setup;
214 ncr_sc->sc_dma_start = si_obio_dma_start;
215 ncr_sc->sc_dma_poll = si_dma_poll;
216 ncr_sc->sc_dma_eop = si_obio_dma_eop;
217 ncr_sc->sc_dma_stop = si_obio_dma_stop;
218 ncr_sc->sc_intr_on = NULL;
219 ncr_sc->sc_intr_off = NULL;
220
221 ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
222
223 #if 1 /* XXX - Temporary */
224 /* XXX - In case we think DMA is completely broken... */
225 if ((si_obio_options & SI_ENABLE_DMA) == 0) {
226 /* Override this function pointer. */
227 ncr_sc->sc_dma_alloc = NULL;
228 }
229 #endif
230
231 /* Need DVMA-capable memory for the UDC command block. */
232 sc->sc_dmacmd = dvma_malloc(sizeof (struct udc_table));
233
234 /* Attach interrupt handler. */
235 isr_add_autovect(si_intr, (void *)sc, intpri);
236
237 /* Do the common attach stuff. */
238 si_attach(sc);
239 }
240
241
242 static __inline__ void
243 si_obio_udc_write(si, regnum, value)
244 volatile struct si_regs *si;
245 int regnum, value;
246 {
247 si->udc_addr = regnum;
248 delay(UDC_WAIT_USEC);
249 si->udc_data = value;
250 delay(UDC_WAIT_USEC);
251 }
252
253 static __inline__ int
254 si_obio_udc_read(si, regnum)
255 volatile struct si_regs *si;
256 int regnum;
257 {
258 int value;
259
260 si->udc_addr = regnum;
261 delay(UDC_WAIT_USEC);
262 value = si->udc_data;
263 delay(UDC_WAIT_USEC);
264
265 return (value);
266 }
267
268
269 /*
270 * This function is called during the COMMAND or MSG_IN phase
271 * that preceeds a DATA_IN or DATA_OUT phase, in case we need
272 * to setup the DMA engine before the bus enters a DATA phase.
273 *
274 * The OBIO "si" IGNORES any attempt to set the FIFO count
275 * register after the SCSI bus goes into any DATA phase, so
276 * this function has to setup the evil FIFO logic.
277 */
278 void
279 si_obio_dma_setup(ncr_sc)
280 struct ncr5380_softc *ncr_sc;
281 {
282 struct si_softc *sc = (struct si_softc *)ncr_sc;
283 struct sci_req *sr = ncr_sc->sc_current;
284 struct si_dma_handle *dh = sr->sr_dma_hand;
285 volatile struct si_regs *si = sc->sc_regs;
286 struct udc_table *cmd;
287 long data_pa, cmd_pa;
288 int xlen;
289
290 /*
291 * Get the DVMA mapping for this segment.
292 * XXX - Should separate allocation and mapin.
293 */
294 data_pa = dvma_kvtopa(dh->dh_dvma, sc->sc_adapter_type);
295 data_pa += (ncr_sc->sc_dataptr - dh->dh_addr);
296 if (data_pa & 1)
297 panic("si_dma_start: bad pa=0x%x", data_pa);
298 xlen = ncr_sc->sc_datalen;
299 sc->sc_reqlen = xlen; /* XXX: or less? */
300
301 #ifdef DEBUG
302 if (si_debug & 2) {
303 printf("si_dma_setup: dh=0x%x, pa=0x%x, xlen=%d\n",
304 dh, data_pa, xlen);
305 }
306 #endif
307
308 /* Reset the UDC. (In case not already reset?) */
309 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
310
311 /* Reset the FIFO */
312 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
313 si->si_csr |= SI_CSR_FIFO_RES;
314
315 /* Set direction (send/recv) */
316 if (dh->dh_flags & SIDH_OUT) {
317 si->si_csr |= SI_CSR_SEND;
318 } else {
319 si->si_csr &= ~SI_CSR_SEND;
320 }
321
322 /* Set the FIFO counter. */
323 si->fifo_count = xlen;
324
325 /* Reset the UDC. */
326 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
327
328 /*
329 * XXX: Reset the FIFO again! Comment from Sprite:
330 * Go through reset again becuase of the bug on the 3/50
331 * where bytes occasionally linger in the DMA fifo.
332 */
333 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
334 si->si_csr |= SI_CSR_FIFO_RES;
335
336 #ifdef DEBUG
337 /* Make sure the extra FIFO reset did not hit the count. */
338 if (si->fifo_count != xlen) {
339 printf("si_dma_setup: fifo_count=0x%x, xlen=0x%x\n",
340 si->fifo_count, xlen);
341 Debugger();
342 }
343 #endif
344
345 /*
346 * Set up the DMA controller. The DMA controller on
347 * OBIO needs a command block in DVMA space.
348 */
349 cmd = sc->sc_dmacmd;
350 cmd->addrh = ((data_pa & 0xFF0000) >> 8) | UDC_ADDR_INFO;
351 cmd->addrl = data_pa & 0xFFFF;
352 cmd->count = xlen / 2; /* bytes -> words */
353 cmd->cmrh = UDC_CMR_HIGH;
354 if (dh->dh_flags & SIDH_OUT) {
355 if (xlen & 1)
356 cmd->count++;
357 cmd->cmrl = UDC_CMR_LSEND;
358 cmd->rsel = UDC_RSEL_SEND;
359 } else {
360 cmd->cmrl = UDC_CMR_LRECV;
361 cmd->rsel = UDC_RSEL_RECV;
362 }
363
364 /* Tell the DMA chip where the control block is. */
365 cmd_pa = dvma_kvtopa((long)cmd, BUS_OBIO);
366 si_obio_udc_write(si, UDC_ADR_CAR_HIGH,
367 (cmd_pa & 0xff0000) >> 8);
368 si_obio_udc_write(si, UDC_ADR_CAR_LOW,
369 (cmd_pa & 0xffff));
370
371 /* Tell the chip to be a DMA master. */
372 si_obio_udc_write(si, UDC_ADR_MODE, UDC_MODE);
373
374 /* Tell the chip to interrupt on error. */
375 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_CIE);
376
377 /* Will do "start chain" command in _dma_start. */
378 }
379
380
381 void
382 si_obio_dma_start(ncr_sc)
383 struct ncr5380_softc *ncr_sc;
384 {
385 struct si_softc *sc = (struct si_softc *)ncr_sc;
386 struct sci_req *sr = ncr_sc->sc_current;
387 struct si_dma_handle *dh = sr->sr_dma_hand;
388 volatile struct si_regs *si = sc->sc_regs;
389 int s;
390
391 #ifdef DEBUG
392 if (si_debug & 2) {
393 printf("si_dma_start: sr=0x%x\n", sr);
394 }
395 #endif
396
397 /* This MAY be time critical (not sure). */
398 s = splhigh();
399
400 /* Finally, give the UDC a "start chain" command. */
401 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_STRT_CHN);
402
403 /*
404 * Acknowledge the phase change. (After DMA setup!)
405 * Put the SBIC into DMA mode, and start the transfer.
406 */
407 if (dh->dh_flags & SIDH_OUT) {
408 *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
409 SCI_CLR_INTR(ncr_sc);
410 *ncr_sc->sci_icmd = SCI_ICMD_DATA;
411 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
412 *ncr_sc->sci_dma_send = 0; /* start it */
413 } else {
414 *ncr_sc->sci_tcmd = PHASE_DATA_IN;
415 SCI_CLR_INTR(ncr_sc);
416 *ncr_sc->sci_icmd = 0;
417 *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
418 *ncr_sc->sci_irecv = 0; /* start it */
419 }
420
421 splx(s);
422 ncr_sc->sc_state |= NCR_DOINGDMA;
423
424 #ifdef DEBUG
425 if (si_debug & 2) {
426 printf("si_dma_start: started, flags=0x%x\n",
427 ncr_sc->sc_state);
428 }
429 #endif
430 }
431
432
433 void
434 si_obio_dma_eop(ncr_sc)
435 struct ncr5380_softc *ncr_sc;
436 {
437
438 /* Not needed - DMA was stopped prior to examining sci_csr */
439 }
440
441
442 void
443 si_obio_dma_stop(ncr_sc)
444 struct ncr5380_softc *ncr_sc;
445 {
446 struct si_softc *sc = (struct si_softc *)ncr_sc;
447 struct sci_req *sr = ncr_sc->sc_current;
448 struct si_dma_handle *dh = sr->sr_dma_hand;
449 volatile struct si_regs *si = sc->sc_regs;
450 int resid, ntrans, tmo, udc_cnt;
451
452 if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
453 #ifdef DEBUG
454 printf("si_dma_stop: dma not running\n");
455 #endif
456 return;
457 }
458 ncr_sc->sc_state &= ~NCR_DOINGDMA;
459
460 NCR_TRACE("si_dma_stop: top, csr=0x%x\n", si->si_csr);
461
462 /* OK, have either phase mis-match or end of DMA. */
463 /* Set an impossible phase to prevent data movement? */
464 *ncr_sc->sci_tcmd = PHASE_INVALID;
465
466 /* Check for DMA errors. */
467 if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
468 printf("si: DMA error, csr=0x%x, reset\n", si->si_csr);
469 sr->sr_xs->error = XS_DRIVER_STUFFUP;
470 ncr_sc->sc_state |= NCR_ABORTING;
471 si_reset_adapter(ncr_sc);
472 goto out;
473 }
474
475 /* Note that timeout may have set the error flag. */
476 if (ncr_sc->sc_state & NCR_ABORTING)
477 goto out;
478
479 /*
480 * After a read, wait for the FIFO to empty.
481 * Note: this only works on the OBIO version.
482 */
483 if ((dh->dh_flags & SIDH_OUT) == 0) {
484 tmo = 200000; /* X10 = 2 sec. */
485 for (;;) {
486 if (si->si_csr & SI_CSR_FIFO_EMPTY)
487 break;
488 if (--tmo <= 0) {
489 printf("si: dma fifo did not empty, reset\n");
490 ncr_sc->sc_state |= NCR_ABORTING;
491 /* si_reset_adapter(ncr_sc); */
492 goto out;
493 }
494 delay(10);
495 }
496 }
497
498 /*
499 * Now try to figure out how much actually transferred
500 * The fifo_count might not reflect how many bytes were
501 * actually transferred.
502 */
503 resid = si->fifo_count & 0xFFFF;
504 ntrans = sc->sc_reqlen - resid;
505
506 #ifdef DEBUG
507 if (si_debug & 2) {
508 printf("si_dma_stop: resid=0x%x ntrans=0x%x\n",
509 resid, ntrans);
510 }
511 #endif
512
513 /* XXX: Treat (ntrans==0) as a special, non-error case? */
514 if (ntrans < MIN_DMA_LEN) {
515 printf("si: fifo count: 0x%x\n", resid);
516 ncr_sc->sc_state |= NCR_ABORTING;
517 goto out;
518 }
519 if (ntrans > ncr_sc->sc_datalen)
520 panic("si_dma_stop: excess transfer");
521
522 /* Adjust data pointer */
523 ncr_sc->sc_dataptr += ntrans;
524 ncr_sc->sc_datalen -= ntrans;
525
526 /*
527 * After a read, we may need to clean-up
528 * "Left-over bytes" (yuck!)
529 */
530 if ((dh->dh_flags & SIDH_OUT) == 0) {
531 /* If odd transfer count, grab last byte by hand. */
532 if (ntrans & 1) {
533 NCR_TRACE("si_dma_stop: leftover 1 at 0x%x\n",
534 (int) ncr_sc->sc_dataptr - 1);
535 ncr_sc->sc_dataptr[-1] =
536 (si->fifo_data & 0xff00) >> 8;
537 goto out;
538 }
539 /* UDC might not have transfered the last word. */
540 udc_cnt = si_obio_udc_read(si, UDC_ADR_COUNT);
541 if (((udc_cnt * 2) - resid) == 2) {
542 NCR_TRACE("si_dma_stop: leftover 2 at 0x%x\n",
543 (int) ncr_sc->sc_dataptr - 2);
544 ncr_sc->sc_dataptr[-2] =
545 (si->fifo_data & 0xff00) >> 8;
546 ncr_sc->sc_dataptr[-1] =
547 (si->fifo_data & 0x00ff);
548 }
549 }
550
551 out:
552 /* Reset the UDC. */
553 si_obio_udc_write(si, UDC_ADR_COMMAND, UDC_CMD_RESET);
554 si->fifo_count = 0;
555 si->si_csr &= ~SI_CSR_SEND;
556
557 /* Reset the FIFO */
558 si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
559 si->si_csr |= SI_CSR_FIFO_RES;
560
561 /* Put SBIC back in PIO mode. */
562 /* XXX: set tcmd to PHASE_INVALID? */
563 *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
564 *ncr_sc->sci_icmd = 0;
565 }
566
567