FreeBSD/Linux Kernel Cross Reference
sys/dev/esp/esp_sbus.c
1 /*-
2 * Copyright (c) 2004 Scott Long
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 /* $NetBSD: esp_sbus.c,v 1.31 2005/02/27 00:27:48 perry Exp $ */
29
30 /*-
31 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
36 * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by the NetBSD
49 * Foundation, Inc. and its contributors.
50 * 4. Neither the name of The NetBSD Foundation nor the names of its
51 * contributors may be used to endorse or promote products derived
52 * from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 #include <sys/cdefs.h>
68 __FBSDID("$FreeBSD$");
69
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/bus.h>
73 #include <sys/kernel.h>
74 #include <sys/module.h>
75 #include <sys/resource.h>
76
77 #include <dev/ofw/ofw_bus.h>
78 #include <dev/ofw/openfirm.h>
79 #include <machine/bus.h>
80 #include <machine/resource.h>
81 #include <sys/rman.h>
82
83 #include <cam/cam.h>
84 #include <cam/cam_ccb.h>
85 #include <cam/scsi/scsi_all.h>
86
87 #include <sparc64/sbus/lsi64854reg.h>
88 #include <sparc64/sbus/lsi64854var.h>
89 #include <sparc64/sbus/sbusvar.h>
90
91 #include <dev/esp/ncr53c9xreg.h>
92 #include <dev/esp/ncr53c9xvar.h>
93
94 /* #define ESP_SBUS_DEBUG */
95
96 struct esp_softc {
97 struct ncr53c9x_softc sc_ncr53c9x; /* glue to MI code */
98 struct device *sc_dev;
99
100 int sc_rid;
101 struct resource *sc_res;
102 bus_space_handle_t sc_regh;
103 bus_space_tag_t sc_regt;
104
105 int sc_irqrid;
106 struct resource *sc_irqres;
107 void *sc_irq;
108
109 struct lsi64854_softc *sc_dma; /* pointer to my DMA */
110 };
111
112 static devclass_t esp_devclass;
113
114 static int esp_probe(device_t);
115 static int esp_dma_attach(device_t);
116 static int esp_dma_detach(device_t);
117 static int esp_sbus_attach(device_t);
118 static int esp_sbus_detach(device_t);
119 static int esp_suspend(device_t);
120 static int esp_resume(device_t);
121
122 static device_method_t esp_dma_methods[] = {
123 DEVMETHOD(device_probe, esp_probe),
124 DEVMETHOD(device_attach, esp_dma_attach),
125 DEVMETHOD(device_detach, esp_dma_detach),
126 DEVMETHOD(device_suspend, esp_suspend),
127 DEVMETHOD(device_resume, esp_resume),
128 {0, 0}
129 };
130
131 static driver_t esp_dma_driver = {
132 "esp",
133 esp_dma_methods,
134 sizeof(struct esp_softc)
135 };
136
137 DRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
138 MODULE_DEPEND(esp, dma, 1, 1, 1);
139
140 static device_method_t esp_sbus_methods[] = {
141 DEVMETHOD(device_probe, esp_probe),
142 DEVMETHOD(device_attach, esp_sbus_attach),
143 DEVMETHOD(device_detach, esp_sbus_detach),
144 DEVMETHOD(device_suspend, esp_suspend),
145 DEVMETHOD(device_resume, esp_resume),
146 {0, 0}
147 };
148
149 static driver_t esp_sbus_driver = {
150 "esp",
151 esp_sbus_methods,
152 sizeof(struct esp_softc)
153 };
154
155 DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
156 MODULE_DEPEND(esp, sbus, 1, 1, 1);
157
158 MODULE_DEPEND(esp, cam, 1, 1, 1);
159
160 /*
161 * Functions and the switch for the MI code
162 */
163 static u_char esp_read_reg(struct ncr53c9x_softc *sc, int reg);
164 static void esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v);
165 static int esp_dma_isintr(struct ncr53c9x_softc *sc);
166 static void esp_dma_reset(struct ncr53c9x_softc *sc);
167 static int esp_dma_intr(struct ncr53c9x_softc *sc);
168 static int esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr,
169 size_t *len, int datain, size_t *dmasize);
170 static void esp_dma_go(struct ncr53c9x_softc *sc);
171 static void esp_dma_stop(struct ncr53c9x_softc *sc);
172 static int esp_dma_isactive(struct ncr53c9x_softc *sc);
173 static int espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep);
174
175 static struct ncr53c9x_glue esp_sbus_glue = {
176 esp_read_reg,
177 esp_write_reg,
178 esp_dma_isintr,
179 esp_dma_reset,
180 esp_dma_intr,
181 esp_dma_setup,
182 esp_dma_go,
183 esp_dma_stop,
184 esp_dma_isactive,
185 NULL, /* gl_clear_latched_intr */
186 };
187
188 static int
189 esp_probe(device_t dev)
190 {
191 const char *name;
192
193 name = ofw_bus_get_name(dev);
194 if (strcmp("SUNW,fas", name) == 0) {
195 device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
196 return (BUS_PROBE_DEFAULT);
197 } else if (strcmp("esp", name) == 0) {
198 device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
199 return (BUS_PROBE_DEFAULT);
200 }
201
202 return (ENXIO);
203 }
204
205 static int
206 esp_sbus_attach(device_t dev)
207 {
208 struct esp_softc *esc;
209 struct ncr53c9x_softc *sc;
210 struct lsi64854_softc *lsc;
211 device_t *children;
212 const char *name;
213 phandle_t node;
214 int burst, error, i, nchildren, slot;
215
216 esc = device_get_softc(dev);
217 bzero(esc, sizeof(struct esp_softc));
218 sc = &esc->sc_ncr53c9x;
219
220 lsc = NULL;
221 esc->sc_dev = dev;
222 name = ofw_bus_get_name(dev);
223 node = ofw_bus_get_node(dev);
224 if (OF_getprop(node, "initiator-id", &sc->sc_id,
225 sizeof(sc->sc_id)) == -1)
226 sc->sc_id = 7;
227 sc->sc_freq = sbus_get_clockfreq(dev);
228
229 #ifdef ESP_SBUS_DEBUG
230 device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
231 sc->sc_freq);
232 #endif
233
234 if (strcmp(name, "SUNW,fas") == 0) {
235 /*
236 * Allocate space for DMA, in SUNW,fas there are no
237 * separate DMA devices.
238 */
239 lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
240 M_NOWAIT | M_ZERO);
241 if (lsc == NULL) {
242 device_printf(dev, "out of memory (lsi64854_softc)\n");
243 return (ENOMEM);
244 }
245 esc->sc_dma = lsc;
246
247 /*
248 * SUNW,fas have 2 register spaces: DMA (lsi64854) and
249 * SCSI core (ncr53c9x).
250 */
251
252 /* Allocate DMA registers. */
253 lsc->sc_rid = 0;
254 if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
255 &lsc->sc_rid, RF_ACTIVE)) == NULL) {
256 device_printf(dev, "cannot allocate DMA registers\n");
257 error = ENXIO;
258 goto fail_sbus_lsc;
259 }
260 lsc->sc_regt = rman_get_bustag(lsc->sc_res);
261 lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
262
263 /* Create a parent DMA tag based on this bus. */
264 error = bus_dma_tag_create(
265 NULL, /* parent */
266 PAGE_SIZE, 0, /* alignment, boundary */
267 BUS_SPACE_MAXADDR, /* lowaddr */
268 BUS_SPACE_MAXADDR, /* highaddr */
269 NULL, NULL, /* filter, filterarg */
270 BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
271 0, /* nsegments */
272 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
273 0, /* flags */
274 NULL, NULL, /* no locking */
275 &lsc->sc_parent_dmat);
276 if (error != 0) {
277 device_printf(dev, "cannot allocate parent DMA tag\n");
278 goto fail_sbus_lres;
279 }
280 burst = sbus_get_burstsz(dev);
281
282 #ifdef ESP_SBUS_DEBUG
283 printf("%s: burst 0x%x\n", __func__, burst);
284 #endif
285
286 lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
287 (burst & SBUS_BURST_16) ? 16 : 0;
288
289 lsc->sc_channel = L64854_CHANNEL_SCSI;
290 lsc->sc_client = sc;
291 lsc->sc_dev = dev;
292
293 error = lsi64854_attach(lsc);
294 if (error != 0) {
295 device_printf(dev, "lsi64854_attach failed\n");
296 goto fail_sbus_lpdma;
297 }
298
299 /*
300 * Allocate SCSI core registers.
301 */
302 esc->sc_rid = 1;
303 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
304 &esc->sc_rid, RF_ACTIVE)) == NULL) {
305 device_printf(dev,
306 "cannot allocate SCSI core registers\n");
307 error = ENXIO;
308 goto fail_sbus_lsi;
309 }
310 esc->sc_regt = rman_get_bustag(esc->sc_res);
311 esc->sc_regh = rman_get_bushandle(esc->sc_res);
312 } else {
313 /*
314 * Search accompanying DMA engine. It should have been
315 * already attached otherwise there isn't much we can do.
316 */
317 if (device_get_children(device_get_parent(dev), &children,
318 &nchildren) != 0) {
319 device_printf(dev, "cannot determine siblings\n");
320 return (ENXIO);
321 }
322 slot = sbus_get_slot(dev);
323 for (i = 0; i < nchildren; i++) {
324 if (device_is_attached(children[i]) &&
325 sbus_get_slot(children[i]) == slot &&
326 strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
327 /* XXX hackery */
328 esc->sc_dma = (struct lsi64854_softc *)
329 device_get_softc(children[i]);
330 break;
331 }
332 }
333 free(children, M_TEMP);
334 if (esc->sc_dma == NULL) {
335 device_printf(dev, "cannot find DMA engine\n");
336 return (ENXIO);
337 }
338 esc->sc_dma->sc_client = sc;
339
340 /*
341 * Allocate SCSI core registers.
342 */
343 esc->sc_rid = 0;
344 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
345 &esc->sc_rid, RF_ACTIVE)) == NULL) {
346 device_printf(dev,
347 "cannot allocate SCSI core registers\n");
348 return (ENXIO);
349 }
350 esc->sc_regt = rman_get_bustag(esc->sc_res);
351 esc->sc_regh = rman_get_bushandle(esc->sc_res);
352 }
353
354 error = espattach(esc, &esp_sbus_glue);
355 if (error != 0) {
356 device_printf(dev, "espattach failed\n");
357 goto fail_sbus_eres;
358 }
359
360 return (0);
361
362 fail_sbus_eres:
363 bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
364 if (strcmp(name, "SUNW,fas") != 0)
365 return (error);
366 fail_sbus_lsi:
367 lsi64854_detach(lsc);
368 fail_sbus_lpdma:
369 bus_dma_tag_destroy(lsc->sc_parent_dmat);
370 fail_sbus_lres:
371 bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
372 fail_sbus_lsc:
373 free(lsc, M_DEVBUF);
374 return (error);
375 }
376
377 static int
378 esp_sbus_detach(device_t dev)
379 {
380 struct esp_softc *esc;
381 struct ncr53c9x_softc *sc;
382 struct lsi64854_softc *lsc;
383 int error;
384
385 esc = device_get_softc(dev);
386 sc = &esc->sc_ncr53c9x;
387 lsc = esc->sc_dma;
388
389 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
390 error = ncr53c9x_detach(sc);
391 if (error != 0)
392 return (error);
393 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
394 esc->sc_irqres);
395 bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
396 if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
397 return (0);
398 error = lsi64854_detach(lsc);
399 if (error != 0)
400 return (error);
401 bus_dma_tag_destroy(lsc->sc_parent_dmat);
402 bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
403 free(lsc, M_DEVBUF);
404
405 return (0);
406 }
407
408 static int
409 esp_dma_attach(device_t dev)
410 {
411 struct esp_softc *esc;
412 struct ncr53c9x_softc *sc;
413 phandle_t node;
414 int error;
415
416 esc = device_get_softc(dev);
417 bzero(esc, sizeof(struct esp_softc));
418 sc = &esc->sc_ncr53c9x;
419
420 esc->sc_dev = dev;
421 node = ofw_bus_get_node(dev);
422 if (OF_getprop(node, "initiator-id", &sc->sc_id,
423 sizeof(sc->sc_id)) == -1)
424 sc->sc_id = 7;
425 if (OF_getprop(node, "clock-frequency", &sc->sc_freq,
426 sizeof(sc->sc_freq)) == -1) {
427 printf("failed to query OFW for clock-frequency\n");
428 return (ENXIO);
429 }
430
431 #ifdef ESP_SBUS_DEBUG
432 device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
433 sc->sc_freq);
434 #endif
435
436 /* XXX hackery */
437 esc->sc_dma = (struct lsi64854_softc *)
438 device_get_softc(device_get_parent(dev));
439 esc->sc_dma->sc_client = sc;
440
441 /*
442 * Allocate SCSI core registers.
443 */
444 esc->sc_rid = 0;
445 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
446 &esc->sc_rid, RF_ACTIVE)) == NULL) {
447 device_printf(dev, "cannot allocate SCSI core registers\n");
448 return (ENXIO);
449 }
450 esc->sc_regt = rman_get_bustag(esc->sc_res);
451 esc->sc_regh = rman_get_bushandle(esc->sc_res);
452
453 error = espattach(esc, &esp_sbus_glue);
454 if (error != 0) {
455 device_printf(dev, "espattach failed\n");
456 goto fail_dma_eres;
457 }
458
459 return (0);
460
461 fail_dma_eres:
462 bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
463 return (error);
464 }
465
466 static int
467 esp_dma_detach(device_t dev)
468 {
469 struct esp_softc *esc;
470 struct ncr53c9x_softc *sc;
471 int error;
472
473 esc = device_get_softc(dev);
474 sc = &esc->sc_ncr53c9x;
475
476 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
477 error = ncr53c9x_detach(sc);
478 if (error != 0)
479 return (error);
480 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
481 esc->sc_irqres);
482 bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
483
484 return (0);
485 }
486
487 static int
488 esp_suspend(device_t dev)
489 {
490
491 return (ENXIO);
492 }
493
494 static int
495 esp_resume(device_t dev)
496 {
497
498 return (ENXIO);
499 }
500
501 static int
502 espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
503 {
504 struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
505 unsigned int uid = 0;
506 int error;
507
508 /*
509 * The `ESC' DMA chip must be reset before we can access
510 * the ESP registers.
511 */
512 if (esc->sc_dma->sc_rev == DMAREV_ESC)
513 DMA_RESET(esc->sc_dma);
514
515 /*
516 * Set up glue for MI code early; we use some of it here.
517 */
518 sc->sc_glue = gluep;
519
520 /* gimme MHz */
521 sc->sc_freq /= 1000000;
522
523 /*
524 * XXX More of this should be in ncr53c9x_attach(), but
525 * XXX should we really poke around the chip that much in
526 * XXX the MI code? Think about this more...
527 */
528
529 /*
530 * Read the part-unique ID code of the SCSI chip. The contained
531 * value is only valid if all of the following conditions are met:
532 * - After power-up or chip reset.
533 * - Before any value is written to this register.
534 * - The NCRCFG2_FE bit is set.
535 * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
536 */
537 NCRCMD(sc, NCRCMD_RSTCHIP);
538 NCRCMD(sc, NCRCMD_NOP);
539 sc->sc_cfg2 = NCRCFG2_FE;
540 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
541 NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
542 uid = NCR_READ_REG(sc, NCR_UID);
543
544 /*
545 * It is necessary to try to load the 2nd config register here,
546 * to find out what rev the esp chip is, else the ncr53c9x_reset
547 * will not set up the defaults correctly.
548 */
549 sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
550 NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
551 sc->sc_cfg2 = 0;
552 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
553 sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
554 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
555
556 if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
557 (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
558 sc->sc_rev = NCR_VARIANT_ESP100;
559 } else {
560 sc->sc_cfg2 = NCRCFG2_SCSI2;
561 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
562 sc->sc_cfg3 = 0;
563 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
564 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
565 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
566 if (NCR_READ_REG(sc, NCR_CFG3) !=
567 (NCRCFG3_CDB | NCRCFG3_FCLK)) {
568 sc->sc_rev = NCR_VARIANT_ESP100A;
569 } else {
570 /* NCRCFG2_FE enables > 64K transfers. */
571 sc->sc_cfg2 |= NCRCFG2_FE;
572 sc->sc_cfg3 = 0;
573 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
574 if (sc->sc_freq <= 25)
575 sc->sc_rev = NCR_VARIANT_ESP200;
576 else {
577 switch ((uid & 0xf8) >> 3) {
578 case 0x00:
579 sc->sc_rev = NCR_VARIANT_FAS100A;
580 break;
581
582 case 0x02:
583 if ((uid & 0x07) == 0x02)
584 sc->sc_rev = NCR_VARIANT_FAS216;
585 else
586 sc->sc_rev = NCR_VARIANT_FAS236;
587 break;
588
589 case 0x0a:
590 sc->sc_rev = NCR_VARIANT_FAS366;
591 break;
592
593 default:
594 /*
595 * We could just treat unknown chips
596 * as ESP200 but then we would most
597 * likely drive them out of specs.
598 */
599 device_printf(esc->sc_dev,
600 "Unknown chip\n");
601 return (ENXIO);
602 }
603 }
604 }
605 }
606
607 #ifdef ESP_SBUS_DEBUG
608 printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
609 #endif
610
611 /*
612 * XXX minsync and maxxfer _should_ be set up in MI code,
613 * XXX but it appears to have some dependency on what sort
614 * XXX of DMA we're hooked up to, etc.
615 */
616
617 /*
618 * This is the value used to start sync negotiations
619 * Note that the NCR register "SYNCTP" is programmed
620 * in "clocks per byte", and has a minimum value of 4.
621 * The SCSI period used in negotiation is one-fourth
622 * of the time (in nanoseconds) needed to transfer one byte.
623 * Since the chip's clock is given in MHz, we have the following
624 * formula: 4 * period = (1000 / freq) * 4
625 */
626 sc->sc_minsync = 1000 / sc->sc_freq;
627
628 sc->sc_maxoffset = 15;
629 sc->sc_extended_geom = 1;
630
631 /*
632 * Alas, we must now modify the value a bit, because it's
633 * only valid when can switch on FASTCLK and FASTSCSI bits
634 * in config register 3...
635 */
636 switch (sc->sc_rev) {
637 case NCR_VARIANT_ESP100:
638 sc->sc_maxwidth = 0;
639 sc->sc_maxxfer = 64 * 1024;
640 sc->sc_minsync = 0; /* No synch on old chip? */
641 break;
642
643 case NCR_VARIANT_ESP100A:
644 sc->sc_maxwidth = 0;
645 sc->sc_maxxfer = 64 * 1024;
646 /* Min clocks/byte is 5 */
647 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
648 break;
649
650 case NCR_VARIANT_ESP200:
651 sc->sc_maxwidth = 0;
652 sc->sc_maxxfer = 16 * 1024 * 1024;
653 /* Min clocks/byte is 5 */
654 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
655 break;
656
657 case NCR_VARIANT_FAS100A:
658 case NCR_VARIANT_FAS216:
659 case NCR_VARIANT_FAS236:
660 /*
661 * The onboard SCSI chips in Sun Ultra 1 are actually
662 * documented to be NCR53C9X which use NCRCFG3_FCLK and
663 * NCRCFG3_FSCSI. BSD/OS however probes these chips as
664 * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI
665 * instead which seems to be correct as otherwise sync
666 * negotiation just doesn't work. Using NCRF9XCFG3_FCLK
667 * and NCRF9XCFG3_FSCSI with these chips in fact also
668 * yields Fast-SCSI speed.
669 */
670 sc->sc_features = NCR_F_FASTSCSI;
671 sc->sc_cfg3 = NCRF9XCFG3_FCLK;
672 sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
673 sc->sc_maxwidth = 0;
674 sc->sc_maxxfer = 16 * 1024 * 1024;
675 break;
676
677 case NCR_VARIANT_FAS366:
678 sc->sc_maxwidth = 1;
679 sc->sc_maxxfer = 16 * 1024 * 1024;
680 break;
681 }
682
683 /* Limit minsync due to unsolved performance issues. */
684 sc->sc_maxsync = sc->sc_minsync;
685
686 /* Establish interrupt channel. */
687 esc->sc_irqrid = 0;
688 if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
689 &esc->sc_irqrid, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
690 device_printf(esc->sc_dev, "cannot allocate interrupt\n");
691 return (ENXIO);
692 }
693 if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
694 INTR_TYPE_BIO|INTR_MPSAFE, ncr53c9x_intr, sc, &esc->sc_irq)) {
695 device_printf(esc->sc_dev, "cannot set up interrupt\n");
696 error = ENXIO;
697 goto fail_ires;
698 }
699
700 /* Turn on target selection using the `DMA' method. */
701 if (sc->sc_rev != NCR_VARIANT_FAS366)
702 sc->sc_features |= NCR_F_DMASELECT;
703
704 /* Do the common parts of attachment. */
705 sc->sc_dev = esc->sc_dev;
706 error = ncr53c9x_attach(sc);
707 if (error != 0) {
708 device_printf(esc->sc_dev, "ncr53c9x_attach failed\n");
709 goto fail_intr;
710 }
711
712 return (0);
713
714 fail_intr:
715 bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
716 fail_ires:
717 bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
718 esc->sc_irqres);
719 return (error);
720 }
721
722 /*
723 * Glue functions
724 */
725
726 #ifdef ESP_SBUS_DEBUG
727 int esp_sbus_debug = 0;
728
729 static struct {
730 char *r_name;
731 int r_flag;
732 } esp__read_regnames [] = {
733 { "TCL", 0}, /* 0/00 */
734 { "TCM", 0}, /* 1/04 */
735 { "FIFO", 0}, /* 2/08 */
736 { "CMD", 0}, /* 3/0c */
737 { "STAT", 0}, /* 4/10 */
738 { "INTR", 0}, /* 5/14 */
739 { "STEP", 0}, /* 6/18 */
740 { "FFLAGS", 1}, /* 7/1c */
741 { "CFG1", 1}, /* 8/20 */
742 { "STAT2", 0}, /* 9/24 */
743 { "CFG4", 1}, /* a/28 */
744 { "CFG2", 1}, /* b/2c */
745 { "CFG3", 1}, /* c/30 */
746 { "-none", 1}, /* d/34 */
747 { "TCH", 1}, /* e/38 */
748 { "TCX", 1}, /* f/3c */
749 };
750
751 static struct {
752 char *r_name;
753 int r_flag;
754 } esp__write_regnames[] = {
755 { "TCL", 1}, /* 0/00 */
756 { "TCM", 1}, /* 1/04 */
757 { "FIFO", 0}, /* 2/08 */
758 { "CMD", 0}, /* 3/0c */
759 { "SELID", 1}, /* 4/10 */
760 { "TIMEOUT", 1}, /* 5/14 */
761 { "SYNCTP", 1}, /* 6/18 */
762 { "SYNCOFF", 1}, /* 7/1c */
763 { "CFG1", 1}, /* 8/20 */
764 { "CCF", 1}, /* 9/24 */
765 { "TEST", 1}, /* a/28 */
766 { "CFG2", 1}, /* b/2c */
767 { "CFG3", 1}, /* c/30 */
768 { "-none", 1}, /* d/34 */
769 { "TCH", 1}, /* e/38 */
770 { "TCX", 1}, /* f/3c */
771 };
772 #endif
773
774 static u_char
775 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
776 {
777 struct esp_softc *esc = (struct esp_softc *)sc;
778 u_char v;
779
780 v = bus_space_read_1(esc->sc_regt, esc->sc_regh, reg * 4);
781 #ifdef ESP_SBUS_DEBUG
782 if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
783 printf("RD:%x <%s> %x\n", reg * 4,
784 ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
785 #endif
786 return v;
787 }
788
789 static void
790 esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
791 {
792 struct esp_softc *esc = (struct esp_softc *)sc;
793
794 #ifdef ESP_SBUS_DEBUG
795 if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
796 printf("WR:%x <%s> %x\n", reg * 4,
797 ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
798 #endif
799 bus_space_write_1(esc->sc_regt, esc->sc_regh, reg * 4, v);
800 }
801
802 static int
803 esp_dma_isintr(struct ncr53c9x_softc *sc)
804 {
805 struct esp_softc *esc = (struct esp_softc *)sc;
806
807 return (DMA_ISINTR(esc->sc_dma));
808 }
809
810 static void
811 esp_dma_reset(struct ncr53c9x_softc *sc)
812 {
813 struct esp_softc *esc = (struct esp_softc *)sc;
814
815 DMA_RESET(esc->sc_dma);
816 }
817
818 static int
819 esp_dma_intr(struct ncr53c9x_softc *sc)
820 {
821 struct esp_softc *esc = (struct esp_softc *)sc;
822
823 return (DMA_INTR(esc->sc_dma));
824 }
825
826 static int
827 esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
828 int datain, size_t *dmasize)
829 {
830 struct esp_softc *esc = (struct esp_softc *)sc;
831
832 return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
833 }
834
835 static void
836 esp_dma_go(struct ncr53c9x_softc *sc)
837 {
838 struct esp_softc *esc = (struct esp_softc *)sc;
839
840 DMA_GO(esc->sc_dma);
841 }
842
843 static void
844 esp_dma_stop(struct ncr53c9x_softc *sc)
845 {
846 struct esp_softc *esc = (struct esp_softc *)sc;
847
848 L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA);
849 }
850
851 static int
852 esp_dma_isactive(struct ncr53c9x_softc *sc)
853 {
854 struct esp_softc *esc = (struct esp_softc *)sc;
855
856 return (DMA_ISACTIVE(esc->sc_dma));
857 }
Cache object: bba1ada094893e8c52a61777cd8dc7cd
|