esp_sbus.c revision 1.12.2.6 1 /* $NetBSD: esp_sbus.c,v 1.12.2.6 2002/01/08 00:31:41 nathanw Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center; 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 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: esp_sbus.c,v 1.12.2.6 2002/01/08 00:31:41 nathanw Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 #include <sys/buf.h>
47 #include <sys/malloc.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/bus.h>
55 #include <machine/intr.h>
56 #include <machine/autoconf.h>
57
58 #include <dev/ic/lsi64854reg.h>
59 #include <dev/ic/lsi64854var.h>
60
61 #include <dev/ic/ncr53c9xreg.h>
62 #include <dev/ic/ncr53c9xvar.h>
63
64 #include <dev/sbus/sbusvar.h>
65
66 /* #define ESP_SBUS_DEBUG */
67
68 struct esp_softc {
69 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
70 struct sbusdev sc_sd; /* sbus device */
71
72 bus_space_tag_t sc_bustag;
73 bus_dma_tag_t sc_dmatag;
74
75 bus_space_handle_t sc_reg; /* the registers */
76 struct lsi64854_softc *sc_dma; /* pointer to my dma */
77
78 int sc_pri; /* SBUS priority */
79 };
80
81 void espattach_sbus __P((struct device *, struct device *, void *));
82 void espattach_dma __P((struct device *, struct device *, void *));
83 int espmatch_sbus __P((struct device *, struct cfdata *, void *));
84
85
86 /* Linkup to the rest of the kernel */
87 struct cfattach esp_sbus_ca = {
88 sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
89 };
90 struct cfattach esp_dma_ca = {
91 sizeof(struct esp_softc), espmatch_sbus, espattach_dma
92 };
93
94 /*
95 * Functions and the switch for the MI code.
96 */
97 static u_char esp_read_reg __P((struct ncr53c9x_softc *, int));
98 static void esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
99 static u_char esp_rdreg1 __P((struct ncr53c9x_softc *, int));
100 static void esp_wrreg1 __P((struct ncr53c9x_softc *, int, u_char));
101 static int esp_dma_isintr __P((struct ncr53c9x_softc *));
102 static void esp_dma_reset __P((struct ncr53c9x_softc *));
103 static int esp_dma_intr __P((struct ncr53c9x_softc *));
104 static int esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
105 size_t *, int, size_t *));
106 static void esp_dma_go __P((struct ncr53c9x_softc *));
107 static void esp_dma_stop __P((struct ncr53c9x_softc *));
108 static int esp_dma_isactive __P((struct ncr53c9x_softc *));
109
110 static struct ncr53c9x_glue esp_sbus_glue = {
111 esp_read_reg,
112 esp_write_reg,
113 esp_dma_isintr,
114 esp_dma_reset,
115 esp_dma_intr,
116 esp_dma_setup,
117 esp_dma_go,
118 esp_dma_stop,
119 esp_dma_isactive,
120 NULL, /* gl_clear_latched_intr */
121 };
122
123 static struct ncr53c9x_glue esp_sbus_glue1 = {
124 esp_rdreg1,
125 esp_wrreg1,
126 esp_dma_isintr,
127 esp_dma_reset,
128 esp_dma_intr,
129 esp_dma_setup,
130 esp_dma_go,
131 esp_dma_stop,
132 esp_dma_isactive,
133 NULL, /* gl_clear_latched_intr */
134 };
135
136 static void espattach __P((struct esp_softc *, struct ncr53c9x_glue *));
137
138 int
139 espmatch_sbus(parent, cf, aux)
140 struct device *parent;
141 struct cfdata *cf;
142 void *aux;
143 {
144 int rv;
145 struct sbus_attach_args *sa = aux;
146
147 if (strcmp("SUNW,fas", sa->sa_name) == 0)
148 return 1;
149
150 rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
151 strcmp("ptscII", sa->sa_name) == 0);
152 return (rv);
153 }
154
155 void
156 espattach_sbus(parent, self, aux)
157 struct device *parent, *self;
158 void *aux;
159 {
160 struct esp_softc *esc = (void *)self;
161 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
162 struct sbus_attach_args *sa = aux;
163 struct lsi64854_softc *lsc;
164 int burst, sbusburst;
165
166 esc->sc_bustag = sa->sa_bustag;
167 esc->sc_dmatag = sa->sa_dmatag;
168
169 sc->sc_id = PROM_getpropint(sa->sa_node, "initiator-id", 7);
170 sc->sc_freq = PROM_getpropint(sa->sa_node, "clock-frequency", -1);
171 if (sc->sc_freq < 0)
172 sc->sc_freq = ((struct sbus_softc *)
173 sc->sc_dev.dv_parent)->sc_clockfreq;
174
175 #ifdef ESP_SBUS_DEBUG
176 printf("%s: espattach_sbus: sc_id %d, freq %d\n",
177 self->dv_xname, sc->sc_id, sc->sc_freq);
178 #endif
179
180 if (strcmp("SUNW,fas", sa->sa_name) == 0) {
181
182 /*
183 * fas has 2 register spaces: dma(lsi64854) and SCSI core (ncr53c9x)
184 */
185 if (sa->sa_nreg != 2) {
186 printf("%s: %d register spaces\n", self->dv_xname, sa->sa_nreg);
187 return;
188 }
189
190 /*
191 * allocate space for dma, in SUNW,fas there are no separate
192 * dma device
193 */
194 lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, M_NOWAIT);
195
196 if (lsc == NULL) {
197 printf("%s: out of memory (lsi64854_softc)\n",
198 self->dv_xname);
199 return;
200 }
201 esc->sc_dma = lsc;
202
203 lsc->sc_bustag = sa->sa_bustag;
204 lsc->sc_dmatag = sa->sa_dmatag;
205
206 bcopy(sc->sc_dev.dv_xname, lsc->sc_dev.dv_xname,
207 sizeof (lsc->sc_dev.dv_xname));
208
209 /* Map dma registers */
210 if (bus_space_map2(sa->sa_bustag,
211 sa->sa_reg[0].sbr_slot,
212 sa->sa_reg[0].sbr_offset,
213 sa->sa_reg[0].sbr_size,
214 BUS_SPACE_MAP_LINEAR,
215 0, &lsc->sc_regs) != 0) {
216 printf("%s: cannot map dma registers\n", self->dv_xname);
217 return;
218 }
219
220 /*
221 * XXX is this common(from bpp.c), the same in dma_sbus...etc.
222 *
223 * Get transfer burst size from PROM and plug it into the
224 * controller registers. This is needed on the Sun4m; do
225 * others need it too?
226 */
227 sbusburst = ((struct sbus_softc *)parent)->sc_burst;
228 if (sbusburst == 0)
229 sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
230
231 burst = PROM_getpropint(sa->sa_node, "burst-sizes", -1);
232
233 #if ESP_SBUS_DEBUG
234 printf("espattach_sbus: burst 0x%x, sbus 0x%x\n",
235 burst, sbusburst);
236 #endif
237
238 if (burst == -1)
239 /* take SBus burst sizes */
240 burst = sbusburst;
241
242 /* Clamp at parent's burst sizes */
243 burst &= sbusburst;
244 lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
245 (burst & SBUS_BURST_16) ? 16 : 0;
246
247 lsc->sc_channel = L64854_CHANNEL_SCSI;
248 lsc->sc_client = sc;
249
250 lsi64854_attach(lsc);
251
252 /*
253 * map SCSI core registers
254 */
255 if (sbus_bus_map(sa->sa_bustag,
256 sa->sa_reg[1].sbr_slot,
257 sa->sa_reg[1].sbr_offset,
258 sa->sa_reg[1].sbr_size,
259 BUS_SPACE_MAP_LINEAR,
260 0, &esc->sc_reg) != 0) {
261 printf("%s @ sbus: cannot map scsi core registers\n",
262 self->dv_xname);
263 return;
264 }
265
266 if (sa->sa_nintr == 0) {
267 printf("\n%s: no interrupt property\n", self->dv_xname);
268 return;
269 }
270
271 esc->sc_pri = sa->sa_pri;
272
273 /* add me to the sbus structures */
274 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
275 sbus_establish(&esc->sc_sd, &sc->sc_dev);
276
277 espattach(esc, &esp_sbus_glue);
278
279 return;
280 }
281
282 /*
283 * Find the DMA by poking around the dma device structures
284 *
285 * What happens here is that if the dma driver has not been
286 * configured, then this returns a NULL pointer. Then when the
287 * dma actually gets configured, it does the opposing test, and
288 * if the sc->sc_esp field in it's softc is NULL, then tries to
289 * find the matching esp driver.
290 */
291 esc->sc_dma = (struct lsi64854_softc *)
292 getdevunit("dma", sc->sc_dev.dv_unit);
293
294 /*
295 * and a back pointer to us, for DMA
296 */
297 if (esc->sc_dma)
298 esc->sc_dma->sc_client = sc;
299 else {
300 printf("\n");
301 panic("espattach: no dma found");
302 }
303
304 /*
305 * The `ESC' DMA chip must be reset before we can access
306 * the esp registers.
307 */
308 if (esc->sc_dma->sc_rev == DMAREV_ESC)
309 DMA_RESET(esc->sc_dma);
310
311 /*
312 * Map my registers in, if they aren't already in virtual
313 * address space.
314 */
315 if (sa->sa_npromvaddrs)
316 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
317 else {
318 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
319 sa->sa_offset,
320 sa->sa_size,
321 BUS_SPACE_MAP_LINEAR,
322 0, &esc->sc_reg) != 0) {
323 printf("%s @ sbus: cannot map registers\n",
324 self->dv_xname);
325 return;
326 }
327 }
328
329 if (sa->sa_nintr == 0) {
330 /*
331 * No interrupt properties: we quit; this might
332 * happen on e.g. a Sparc X terminal.
333 */
334 printf("\n%s: no interrupt property\n", self->dv_xname);
335 return;
336 }
337
338 esc->sc_pri = sa->sa_pri;
339
340 /* add me to the sbus structures */
341 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
342 sbus_establish(&esc->sc_sd, &sc->sc_dev);
343
344 if (strcmp("ptscII", sa->sa_name) == 0) {
345 espattach(esc, &esp_sbus_glue1);
346 } else {
347 espattach(esc, &esp_sbus_glue);
348 }
349 }
350
351 void
352 espattach_dma(parent, self, aux)
353 struct device *parent, *self;
354 void *aux;
355 {
356 struct esp_softc *esc = (void *)self;
357 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
358 struct sbus_attach_args *sa = aux;
359
360 if (strcmp("ptscII", sa->sa_name) == 0) {
361 return;
362 }
363
364 esc->sc_bustag = sa->sa_bustag;
365 esc->sc_dmatag = sa->sa_dmatag;
366
367 sc->sc_id = PROM_getpropint(sa->sa_node, "initiator-id", 7);
368 sc->sc_freq = PROM_getpropint(sa->sa_node, "clock-frequency", -1);
369
370 esc->sc_dma = (struct lsi64854_softc *)parent;
371 esc->sc_dma->sc_client = sc;
372
373 /*
374 * Map my registers in, if they aren't already in virtual
375 * address space.
376 */
377 if (sa->sa_npromvaddrs)
378 esc->sc_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
379 else {
380 if (bus_space_map2(sa->sa_bustag,
381 sa->sa_slot,
382 sa->sa_offset,
383 sa->sa_size,
384 BUS_SPACE_MAP_LINEAR,
385 0, &esc->sc_reg) != 0) {
386 printf("%s @ dma: cannot map registers\n",
387 self->dv_xname);
388 return;
389 }
390 }
391
392 if (sa->sa_nintr == 0) {
393 /*
394 * No interrupt properties: we quit; this might
395 * happen on e.g. a Sparc X terminal.
396 */
397 printf("\n%s: no interrupt property\n", self->dv_xname);
398 return;
399 }
400
401 esc->sc_pri = sa->sa_pri;
402
403 /* Assume SBus is grandparent */
404 esc->sc_sd.sd_reset = (void *) ncr53c9x_reset;
405 sbus_establish(&esc->sc_sd, parent);
406
407 espattach(esc, &esp_sbus_glue);
408 }
409
410
411 /*
412 * Attach this instance, and then all the sub-devices
413 */
414 void
415 espattach(esc, gluep)
416 struct esp_softc *esc;
417 struct ncr53c9x_glue *gluep;
418 {
419 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
420 void *icookie;
421 unsigned int uid = 0;
422
423 /*
424 * Set up glue for MI code early; we use some of it here.
425 */
426 sc->sc_glue = gluep;
427
428 /* gimme Mhz */
429 sc->sc_freq /= 1000000;
430
431 /*
432 * XXX More of this should be in ncr53c9x_attach(), but
433 * XXX should we really poke around the chip that much in
434 * XXX the MI code? Think about this more...
435 */
436
437 /*
438 * It is necessary to try to load the 2nd config register here,
439 * to find out what rev the esp chip is, else the ncr53c9x_reset
440 * will not set up the defaults correctly.
441 */
442 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
443 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
444 sc->sc_cfg3 = NCRCFG3_CDB;
445 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
446
447 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
448 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
449 sc->sc_rev = NCR_VARIANT_ESP100;
450 } else {
451 sc->sc_cfg2 = NCRCFG2_SCSI2;
452 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
453 sc->sc_cfg3 = 0;
454 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
455 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
456 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
457 if (NCR_READ_REG(sc, NCR_CFG3) !=
458 (NCRCFG3_CDB | NCRCFG3_FCLK)) {
459 sc->sc_rev = NCR_VARIANT_ESP100A;
460 } else {
461 /* NCRCFG2_FE enables > 64K transfers */
462 sc->sc_cfg2 |= NCRCFG2_FE;
463 sc->sc_cfg3 = 0;
464 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
465 sc->sc_rev = NCR_VARIANT_ESP200;
466
467 /* XXX spec says it's valid after power up or chip reset */
468 uid = NCR_READ_REG(sc, NCR_UID);
469 if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
470 sc->sc_rev = NCR_VARIANT_FAS366;
471 }
472 }
473
474 #ifdef ESP_SBUS_DEBUG
475 printf("espattach: revision %d, uid 0x%x\n", sc->sc_rev, uid);
476 #endif
477
478 /*
479 * XXX minsync and maxxfer _should_ be set up in MI code,
480 * XXX but it appears to have some dependency on what sort
481 * XXX of DMA we're hooked up to, etc.
482 */
483
484 /*
485 * This is the value used to start sync negotiations
486 * Note that the NCR register "SYNCTP" is programmed
487 * in "clocks per byte", and has a minimum value of 4.
488 * The SCSI period used in negotiation is one-fourth
489 * of the time (in nanoseconds) needed to transfer one byte.
490 * Since the chip's clock is given in MHz, we have the following
491 * formula: 4 * period = (1000 / freq) * 4
492 */
493 sc->sc_minsync = 1000 / sc->sc_freq;
494
495 /*
496 * Alas, we must now modify the value a bit, because it's
497 * only valid when can switch on FASTCLK and FASTSCSI bits
498 * in config register 3...
499 */
500 switch (sc->sc_rev) {
501 case NCR_VARIANT_ESP100:
502 sc->sc_maxxfer = 64 * 1024;
503 sc->sc_minsync = 0; /* No synch on old chip? */
504 break;
505
506 case NCR_VARIANT_ESP100A:
507 sc->sc_maxxfer = 64 * 1024;
508 /* Min clocks/byte is 5 */
509 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
510 break;
511
512 case NCR_VARIANT_ESP200:
513 case NCR_VARIANT_FAS366:
514 sc->sc_maxxfer = 16 * 1024 * 1024;
515 /* XXX - do actually set FAST* bits */
516 break;
517 }
518
519 /* Establish interrupt channel */
520 icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0,
521 ncr53c9x_intr, sc);
522
523 /* register interrupt stats */
524 evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
525 sc->sc_dev.dv_xname, "intr");
526
527 /* Turn on target selection using the `dma' method */
528 if (sc->sc_rev != NCR_VARIANT_FAS366)
529 sc->sc_features |= NCR_F_DMASELECT;
530
531 /* Do the common parts of attachment. */
532 sc->sc_adapter.adapt_minphys = minphys;
533 sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
534 ncr53c9x_attach(sc);
535
536 }
537
538 /*
539 * Glue functions.
540 */
541
542 #ifdef ESP_SBUS_DEBUG
543 int esp_sbus_debug = 0;
544
545 static struct {
546 char *r_name;
547 int r_flag;
548 } esp__read_regnames [] = {
549 { "TCL", 0}, /* 0/00 */
550 { "TCM", 0}, /* 1/04 */
551 { "FIFO", 0}, /* 2/08 */
552 { "CMD", 0}, /* 3/0c */
553 { "STAT", 0}, /* 4/10 */
554 { "INTR", 0}, /* 5/14 */
555 { "STEP", 0}, /* 6/18 */
556 { "FFLAGS", 1}, /* 7/1c */
557 { "CFG1", 1}, /* 8/20 */
558 { "STAT2", 0}, /* 9/24 */
559 { "CFG4", 1}, /* a/28 */
560 { "CFG2", 1}, /* b/2c */
561 { "CFG3", 1}, /* c/30 */
562 { "-none", 1}, /* d/34 */
563 { "TCH", 1}, /* e/38 */
564 { "TCX", 1}, /* f/3c */
565 };
566
567 static struct {
568 char *r_name;
569 int r_flag;
570 } esp__write_regnames[] = {
571 { "TCL", 1}, /* 0/00 */
572 { "TCM", 1}, /* 1/04 */
573 { "FIFO", 0}, /* 2/08 */
574 { "CMD", 0}, /* 3/0c */
575 { "SELID", 1}, /* 4/10 */
576 { "TIMEOUT", 1}, /* 5/14 */
577 { "SYNCTP", 1}, /* 6/18 */
578 { "SYNCOFF", 1}, /* 7/1c */
579 { "CFG1", 1}, /* 8/20 */
580 { "CCF", 1}, /* 9/24 */
581 { "TEST", 1}, /* a/28 */
582 { "CFG2", 1}, /* b/2c */
583 { "CFG3", 1}, /* c/30 */
584 { "-none", 1}, /* d/34 */
585 { "TCH", 1}, /* e/38 */
586 { "TCX", 1}, /* f/3c */
587 };
588 #endif
589
590 u_char
591 esp_read_reg(sc, reg)
592 struct ncr53c9x_softc *sc;
593 int reg;
594 {
595 struct esp_softc *esc = (struct esp_softc *)sc;
596 u_char v;
597
598 v = bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
599 #ifdef ESP_SBUS_DEBUG
600 if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
601 printf("RD:%x <%s> %x\n", reg * 4,
602 ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
603 #endif
604 return v;
605 }
606
607 void
608 esp_write_reg(sc, reg, v)
609 struct ncr53c9x_softc *sc;
610 int reg;
611 u_char v;
612 {
613 struct esp_softc *esc = (struct esp_softc *)sc;
614
615 #ifdef ESP_SBUS_DEBUG
616 if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
617 printf("WR:%x <%s> %x\n", reg * 4,
618 ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
619 #endif
620 bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
621 }
622
623 u_char
624 esp_rdreg1(sc, reg)
625 struct ncr53c9x_softc *sc;
626 int reg;
627 {
628 struct esp_softc *esc = (struct esp_softc *)sc;
629
630 return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg));
631 }
632
633 void
634 esp_wrreg1(sc, reg, v)
635 struct ncr53c9x_softc *sc;
636 int reg;
637 u_char v;
638 {
639 struct esp_softc *esc = (struct esp_softc *)sc;
640
641 bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
642 }
643
644 int
645 esp_dma_isintr(sc)
646 struct ncr53c9x_softc *sc;
647 {
648 struct esp_softc *esc = (struct esp_softc *)sc;
649
650 return (DMA_ISINTR(esc->sc_dma));
651 }
652
653 void
654 esp_dma_reset(sc)
655 struct ncr53c9x_softc *sc;
656 {
657 struct esp_softc *esc = (struct esp_softc *)sc;
658
659 DMA_RESET(esc->sc_dma);
660 }
661
662 int
663 esp_dma_intr(sc)
664 struct ncr53c9x_softc *sc;
665 {
666 struct esp_softc *esc = (struct esp_softc *)sc;
667
668 return (DMA_INTR(esc->sc_dma));
669 }
670
671 int
672 esp_dma_setup(sc, addr, len, datain, dmasize)
673 struct ncr53c9x_softc *sc;
674 caddr_t *addr;
675 size_t *len;
676 int datain;
677 size_t *dmasize;
678 {
679 struct esp_softc *esc = (struct esp_softc *)sc;
680
681 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
682 }
683
684 void
685 esp_dma_go(sc)
686 struct ncr53c9x_softc *sc;
687 {
688 struct esp_softc *esc = (struct esp_softc *)sc;
689
690 DMA_GO(esc->sc_dma);
691 }
692
693 void
694 esp_dma_stop(sc)
695 struct ncr53c9x_softc *sc;
696 {
697 struct esp_softc *esc = (struct esp_softc *)sc;
698 u_int32_t csr;
699
700 csr = L64854_GCSR(esc->sc_dma);
701 csr &= ~D_EN_DMA;
702 L64854_SCSR(esc->sc_dma, csr);
703 }
704
705 int
706 esp_dma_isactive(sc)
707 struct ncr53c9x_softc *sc;
708 {
709 struct esp_softc *esc = (struct esp_softc *)sc;
710
711 return (DMA_ISACTIVE(esc->sc_dma));
712 }
713
714 #include "opt_ddb.h"
715 #ifdef DDB
716 #include <machine/db_machdep.h>
717 #include <ddb/db_output.h>
718
719 void db_esp __P((db_expr_t, int, db_expr_t, char*));
720
721 void
722 db_esp(addr, have_addr, count, modif)
723 db_expr_t addr;
724 int have_addr;
725 db_expr_t count;
726 char *modif;
727 {
728 struct ncr53c9x_softc *sc;
729 struct ncr53c9x_ecb *ecb;
730 struct ncr53c9x_linfo *li;
731 int u, t, i;
732
733 for (u=0; u<10; u++) {
734 sc = (struct ncr53c9x_softc *)
735 getdevunit("esp", u);
736 if (!sc) continue;
737
738 db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n",
739 u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
740 sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
741 db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
742 sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
743 sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
744 sc->sc_imess[0]);
745 db_printf("ready: ");
746 for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) {
747 db_printf("ecb %p ", ecb);
748 if (ecb == ecb->chain.tqe_next) {
749 db_printf("\nWARNING: tailq loop on ecb %p", ecb);
750 break;
751 }
752 }
753 db_printf("\n");
754
755 for (t=0; t<NCR_NTARG; t++) {
756 LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
757 db_printf("t%d lun %d untagged %p busy %d used %x\n",
758 t, (int)li->lun, li->untagged, li->busy,
759 li->used);
760 for (i=0; i<256; i++)
761 if ((ecb = li->queued[i])) {
762 db_printf("ecb %p tag %x\n", ecb, i);
763 }
764 }
765 }
766 }
767 }
768 #endif
769
770