asc.c revision 1.13 1 /* $NetBSD: asc.c,v 1.13 2003/04/02 04:00:46 thorpej Exp $ */
2 /*-
3 * Copyright (c) 2000 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Wayne Knowles
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/errno.h>
43 #include <sys/device.h>
44 #include <sys/buf.h>
45 #include <sys/malloc.h>
46
47 #include <uvm/uvm_extern.h>
48
49 #include <dev/scsipi/scsi_all.h>
50 #include <dev/scsipi/scsipi_all.h>
51 #include <dev/scsipi/scsiconf.h>
52 #include <dev/scsipi/scsi_message.h>
53
54 #include <machine/cpu.h>
55 #include <machine/autoconf.h>
56 #include <machine/mainboard.h>
57 #include <machine/bus.h>
58
59 #include <mipsco/obio/rambo.h>
60
61 #include <dev/ic/ncr53c9xreg.h>
62 #include <dev/ic/ncr53c9xvar.h>
63
64 struct asc_softc {
65 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
66 struct evcnt sc_intrcnt; /* Interrupt counter */
67 bus_space_tag_t sc_bst;
68 bus_space_handle_t sc_bsh; /* NCR 53c94 registers */
69 bus_space_handle_t dm_bsh; /* RAMBO registers */
70 bus_dma_tag_t sc_dmat;
71 bus_dmamap_t sc_dmamap;
72 caddr_t *sc_dmaaddr;
73 size_t *sc_dmalen;
74 size_t sc_dmasize;
75 int sc_flags;
76 #define DMA_IDLE 0x0
77 #define DMA_PULLUP 0x1
78 #define DMA_ACTIVE 0x2
79 #define DMA_MAPLOADED 0x4
80 u_int32_t dm_mode;
81 int dm_curseg;
82 };
83
84 static int ascmatch (struct device *, struct cfdata *, void *);
85 static void ascattach (struct device *, struct device *, void *);
86
87 CFATTACH_DECL(asc, sizeof(struct asc_softc),
88 ascmatch, ascattach, NULL, NULL);
89
90 /*
91 * Functions and the switch for the MI code.
92 */
93 static u_char asc_read_reg (struct ncr53c9x_softc *, int);
94 static void asc_write_reg (struct ncr53c9x_softc *, int, u_char);
95 static int asc_dma_isintr (struct ncr53c9x_softc *);
96 static void asc_dma_reset (struct ncr53c9x_softc *);
97 static int asc_dma_intr (struct ncr53c9x_softc *);
98 static int asc_dma_setup (struct ncr53c9x_softc *, caddr_t *,
99 size_t *, int, size_t *);
100 static void asc_dma_go (struct ncr53c9x_softc *);
101 static void asc_dma_stop (struct ncr53c9x_softc *);
102 static int asc_dma_isactive (struct ncr53c9x_softc *);
103
104 static struct ncr53c9x_glue asc_glue = {
105 asc_read_reg,
106 asc_write_reg,
107 asc_dma_isintr,
108 asc_dma_reset,
109 asc_dma_intr,
110 asc_dma_setup,
111 asc_dma_go,
112 asc_dma_stop,
113 asc_dma_isactive,
114 NULL, /* gl_clear_latched_intr */
115 };
116
117 static int asc_intr (void *);
118
119 #define MAX_SCSI_XFER (64*1024)
120 #define MAX_DMA_SZ MAX_SCSI_XFER
121 #define DMA_SEGS (MAX_DMA_SZ/PAGE_SIZE)
122
123 static int
124 ascmatch(struct device *parent, struct cfdata *cf, void *aux)
125 {
126 return 1;
127 }
128
129 static void
130 ascattach(struct device *parent, struct device *self, void *aux)
131 {
132 struct confargs *ca = aux;
133 struct asc_softc *esc = (void *)self;
134 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
135
136 /*
137 * Set up glue for MI code early; we use some of it here.
138 */
139 sc->sc_glue = &asc_glue;
140
141 esc->sc_bst = ca->ca_bustag;
142 esc->sc_dmat = ca->ca_dmatag;
143
144 if (bus_space_map(ca->ca_bustag, ca->ca_addr,
145 16*4, /* sizeof (ncr53c9xreg) */
146 BUS_SPACE_MAP_LINEAR,
147 &esc->sc_bsh) != 0) {
148 printf(": cannot map registers\n");
149 return;
150 }
151
152 if (bus_space_map(ca->ca_bustag, RAMBO_BASE, sizeof(struct rambo_ch),
153 BUS_SPACE_MAP_LINEAR,
154 &esc->dm_bsh) != 0) {
155 printf(": cannot map dma registers\n");
156 return;
157 }
158
159 if (bus_dmamap_create(esc->sc_dmat, MAX_DMA_SZ,
160 DMA_SEGS, MAX_DMA_SZ, RB_BOUNDRY,
161 BUS_DMA_WAITOK,
162 &esc->sc_dmamap) != 0) {
163 printf(": failed to create dmamap\n");
164 return;
165 }
166
167 evcnt_attach_dynamic(&esc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
168 self->dv_xname, "intr");
169
170 esc->sc_flags = DMA_IDLE;
171 asc_dma_reset(sc);
172
173 /* Other settings */
174 sc->sc_id = 7;
175 sc->sc_freq = 24; /* 24 MHz clock */
176
177 /*
178 * Setup for genuine NCR 53C94 SCSI Controller
179 */
180
181 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
182 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_FE;
183 sc->sc_cfg3 = NCRCFG3_CDB | NCRCFG3_QTE | NCRCFG3_FSCSI;
184 sc->sc_rev = NCR_VARIANT_NCR53C94;
185
186 sc->sc_minsync = (1000 / sc->sc_freq) * 5 / 4;
187 sc->sc_maxxfer = MAX_SCSI_XFER;
188
189 #ifdef OLDNCR
190 if (!NCR_READ_REG(sc, NCR_CFG3)) {
191 printf(" [old revision]");
192 sc->sc_cfg2 = 0;
193 sc->sc_cfg3 = 0;
194 sc->sc_minsync = 0;
195 }
196 #endif
197
198 sc->sc_adapter.adapt_minphys = minphys;
199 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
200 ncr53c9x_attach(sc);
201
202 bus_intr_establish(esc->sc_bst, SYS_INTR_SCSI, 0, 0, asc_intr, esc);
203 }
204
205 /*
206 * Glue functions.
207 */
208
209 static u_char
210 asc_read_reg(struct ncr53c9x_softc *sc, int reg)
211 {
212 struct asc_softc *esc = (struct asc_softc *)sc;
213
214 return bus_space_read_1(esc->sc_bst, esc->sc_bsh, reg * 4 + 3);
215 }
216
217 static void
218 asc_write_reg(struct ncr53c9x_softc *sc, int reg, u_char val)
219 {
220 struct asc_softc *esc = (struct asc_softc *)sc;
221
222 bus_space_write_1(esc->sc_bst, esc->sc_bsh, reg * 4 + 3, val);
223 }
224
225 static void
226 dma_status(struct ncr53c9x_softc *sc)
227 {
228 struct asc_softc *esc = (struct asc_softc *)sc;
229 int count;
230 int stat;
231 void *addr;
232 u_int32_t tc;
233
234 tc = (asc_read_reg(sc, NCR_TCM)<<8) + asc_read_reg(sc, NCR_TCL);
235 count = bus_space_read_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT);
236 stat = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE);
237 addr = (void *)
238 bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_CADDR);
239
240 printf("rambo status: cnt=%x addr=%p stat=%08x tc=%04x "
241 "ncr_stat=0x%02x ncr_fifo=0x%02x\n",
242 count, addr, stat, tc,
243 asc_read_reg(sc, NCR_STAT),
244 asc_read_reg(sc, NCR_FFLAG));
245 }
246
247 static __inline void
248 check_fifo(struct asc_softc *esc)
249 {
250 register int i=100;
251
252 while (i && !(bus_space_read_4(esc->sc_bst, esc->dm_bsh,
253 RAMBO_MODE) & RB_FIFO_EMPTY)) {
254 DELAY(1); i--;
255 }
256
257 if (!i) {
258 dma_status((void *)esc);
259 panic("fifo didn't flush");
260 }
261 }
262
263 static int
264 asc_dma_isintr(struct ncr53c9x_softc *sc)
265 {
266 return NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT;
267 }
268
269 static void
270 asc_dma_reset(struct ncr53c9x_softc *sc)
271 {
272 struct asc_softc *esc = (struct asc_softc *)sc;
273
274 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, 0);
275 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE,
276 RB_CLRFIFO|RB_CLRERROR);
277 DELAY(10);
278 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0);
279
280 if (esc->sc_flags & DMA_MAPLOADED)
281 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap);
282
283 esc->sc_flags = DMA_IDLE;
284 }
285
286 /*
287 * Setup a DMA transfer
288 */
289
290 static int
291 asc_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
292 int datain, size_t *dmasize)
293 {
294 struct asc_softc *esc = (struct asc_softc *)sc;
295 paddr_t paddr;
296 size_t count, blocks;
297 int prime, err;
298
299 #ifdef DIAGNOSTIC
300 if (esc->sc_flags & DMA_ACTIVE) {
301 dma_status(sc);
302 panic("DMA active");
303 }
304 #endif
305
306 esc->sc_dmaaddr = addr;
307 esc->sc_dmalen = len;
308 esc->sc_dmasize = *dmasize;
309 esc->sc_flags = datain ? DMA_PULLUP : 0;
310
311 NCR_DMA(("asc_dma_setup va=%p len=%d datain=%d count=%d\n",
312 *addr, *len, datain, esc->sc_dmasize));
313
314 if (esc->sc_dmasize == 0)
315 return 0;
316
317 /* have dmamap for the transfering addresses */
318 if ((err=bus_dmamap_load(esc->sc_dmat, esc->sc_dmamap,
319 *esc->sc_dmaaddr, esc->sc_dmasize,
320 NULL /* kernel address */,
321 BUS_DMA_NOWAIT)) != 0)
322 panic("%s: bus_dmamap_load err=%d", sc->sc_dev.dv_xname, err);
323
324 esc->sc_flags |= DMA_MAPLOADED;
325
326 paddr = esc->sc_dmamap->dm_segs[0].ds_addr;
327 count = esc->sc_dmamap->dm_segs[0].ds_len;
328 prime = (u_int32_t)paddr & 0x3f;
329 blocks = (prime + count + 63) >> 6;
330
331 esc->dm_mode = (datain ? RB_DMA_WR : RB_DMA_RD);
332
333 /* Set transfer direction and disable DMA */
334 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, esc->dm_mode);
335
336 /* Load DMA transfer address */
337 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_LADDR,
338 paddr & ~0x3f);
339
340 /* Load number of blocks to DMA (1 block = 64 bytes) */
341 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, blocks);
342
343 /* If non block-aligned transfer prime FIFO manually */
344 if (prime) {
345 /* Enable DMA to prime the FIFO buffer */
346 bus_space_write_4(esc->sc_bst, esc->dm_bsh,
347 RAMBO_MODE, esc->dm_mode | RB_DMA_ENABLE);
348
349 if (esc->sc_flags & DMA_PULLUP) {
350 /* Read from NCR 53c94 controller*/
351 u_int16_t *p;
352
353 p = (u_int16_t *)((u_int32_t)*esc->sc_dmaaddr & ~0x3f);
354 bus_space_write_multi_2(esc->sc_bst, esc->dm_bsh,
355 RAMBO_FIFO, p, prime>>1);
356 } else
357 /* Write to NCR 53C94 controller */
358 while (prime > 0) {
359 (void)bus_space_read_2(esc->sc_bst,
360 esc->dm_bsh,
361 RAMBO_FIFO);
362 prime -= 2;
363 }
364 /* Leave DMA disabled while we setup NCR controller */
365 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE,
366 esc->dm_mode);
367 }
368
369 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmamap, 0, esc->sc_dmasize,
370 datain ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
371
372 esc->dm_curseg = 0;
373 esc->dm_mode |= RB_DMA_ENABLE;
374 if (esc->sc_dmamap->dm_nsegs > 1)
375 esc->dm_mode |= RB_INT_ENABLE; /* Requires DMA chaining */
376
377 return 0;
378 }
379
380 static void
381 asc_dma_go(struct ncr53c9x_softc *sc)
382 {
383 struct asc_softc *esc = (struct asc_softc *)sc;
384
385 /* Start DMA */
386 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, esc->dm_mode);
387
388 esc->sc_flags |= DMA_ACTIVE;
389 }
390
391 static int
392 asc_dma_intr(struct ncr53c9x_softc *sc)
393 {
394 struct asc_softc *esc = (struct asc_softc *)sc;
395
396 size_t resid, len;
397 int trans;
398 u_int32_t status;
399 u_int tcl, tcm;
400
401 #ifdef DIAGNOSTIC
402 if (!(esc->sc_flags & DMA_ACTIVE)) {
403 dma_status(sc);
404 panic("DMA not active");
405 }
406 #endif
407
408 resid = 0;
409 if (!(esc->sc_flags & DMA_PULLUP) &&
410 (resid = (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF)) != 0) {
411 NCR_DMA(("asc_intr: empty FIFO of %d ", resid));
412 DELAY(10);
413 }
414
415 resid += (tcl = NCR_READ_REG(sc, NCR_TCL)) +
416 ((tcm = NCR_READ_REG(sc, NCR_TCM)) << 8);
417
418 if (esc->sc_dmasize == 0) { /* Transfer pad operation */
419 NCR_DMA(("asc_intr: discard %d bytes\n", resid));
420 return 0;
421 }
422
423 trans = esc->sc_dmasize - resid;
424 if (trans < 0) { /* transferred < 0 ? */
425 printf("asc_intr: xfer (%d) > req (%d)\n",
426 trans, esc->sc_dmasize);
427 trans = esc->sc_dmasize;
428 }
429
430 NCR_DMA(("asc_intr: tcl=%d, tcm=%d; trans=%d, resid=%d\n",
431 tcl, tcm, trans, resid));
432
433 status = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE);
434
435 if (!(status & RB_FIFO_EMPTY)) { /* Data left in RAMBO FIFO */
436 if (esc->sc_flags & DMA_PULLUP) { /* SCSI Read */
437 paddr_t ptr;
438 u_int16_t *p;
439
440 resid = status & 0x1f;
441
442 /* take the address of block to fixed up */
443 ptr = bus_space_read_4(esc->sc_bst, esc->dm_bsh,
444 RAMBO_CADDR);
445 /* find the starting address of fractional data */
446 p = (u_int16_t *)MIPS_PHYS_TO_KSEG0(ptr+(resid<<1));
447
448 /* duplicate trailing data to FIFO for force flush */
449 len = RB_BLK_CNT - resid;
450 bus_space_write_multi_2(esc->sc_bst, esc->dm_bsh,
451 RAMBO_FIFO, p, len);
452 check_fifo(esc);
453 } else { /* SCSI Write */
454 bus_space_write_4(esc->sc_bst, esc->dm_bsh,
455 RAMBO_MODE, 0);
456 bus_space_write_4(esc->sc_bst, esc->dm_bsh,
457 RAMBO_MODE, RB_CLRFIFO);
458 }
459 }
460
461 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, 0);
462
463 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0);
464
465 bus_dmamap_sync(esc->sc_dmat, esc->sc_dmamap,
466 0, esc->sc_dmasize,
467 (esc->sc_flags & DMA_PULLUP)
468 ? BUS_DMASYNC_POSTREAD
469 : BUS_DMASYNC_POSTWRITE);
470 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap);
471
472 *esc->sc_dmaaddr += trans;
473 *esc->sc_dmalen -= trans;
474
475 esc->sc_flags = DMA_IDLE;
476
477 return 0;
478 }
479
480
481 static void
482 asc_dma_stop(struct ncr53c9x_softc *sc)
483 {
484 struct asc_softc *esc = (struct asc_softc *)sc;
485
486 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE, 0);
487 if (esc->sc_flags & DMA_MAPLOADED)
488 bus_dmamap_unload(esc->sc_dmat, esc->sc_dmamap);
489 esc->sc_flags = DMA_IDLE;
490 }
491
492 static int
493 asc_dma_isactive(struct ncr53c9x_softc *sc)
494 {
495 struct asc_softc *esc = (struct asc_softc *)sc;
496 return (esc->sc_flags & DMA_ACTIVE)? 1 : 0;
497 }
498
499 static void
500 rambo_dma_chain(struct asc_softc *esc)
501 {
502 int seg;
503 size_t count, blocks;
504 paddr_t paddr;
505
506 seg = ++esc->dm_curseg;
507
508 #ifdef DIAGNOSTIC
509 if (!(esc->sc_flags & DMA_ACTIVE) || seg > esc->sc_dmamap->dm_nsegs)
510 panic("Unexpected DMA chaining intr");
511
512 /* Interrupt can only occur at terminal count, but double check */
513 if (bus_space_read_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT)) {
514 dma_status((void *)esc);
515 panic("rambo blkcnt != 0");
516 }
517 #endif
518
519 paddr = esc->sc_dmamap->dm_segs[seg].ds_addr;
520 count = esc->sc_dmamap->dm_segs[seg].ds_len;
521 blocks = (count + 63) >> 6;
522
523 /* Disable DMA interrupt if last segment */
524 if (seg+1 > esc->sc_dmamap->dm_nsegs) {
525 bus_space_write_4(esc->sc_bst, esc->dm_bsh,
526 RAMBO_MODE, esc->dm_mode & ~RB_INT_ENABLE);
527 }
528
529 /* Load transfer address for next DMA chain */
530 bus_space_write_4(esc->sc_bst, esc->dm_bsh, RAMBO_LADDR, paddr);
531
532 /* DMA restarts when we enter a new block count */
533 bus_space_write_2(esc->sc_bst, esc->dm_bsh, RAMBO_BLKCNT, blocks);
534 }
535
536 static int
537 asc_intr(void *arg)
538 {
539 register u_int32_t dma_stat;
540 struct asc_softc *esc = arg;
541 struct ncr53c9x_softc *sc = arg;
542
543 esc->sc_intrcnt.ev_count++;
544
545 /* Check for RAMBO DMA Interrupt */
546 dma_stat = bus_space_read_4(esc->sc_bst, esc->dm_bsh, RAMBO_MODE);
547 if (dma_stat & RB_INTR_PEND) {
548 rambo_dma_chain(esc);
549 }
550 /* Check for NCR 53c94 interrupt */
551 if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT) {
552 ncr53c9x_intr(sc);
553 }
554 return 0;
555 }
556