1 /* $NetBSD: esp_isa.c,v 1.35 2008/04/13 04:55:53 tsutsui Exp $ */
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1994 Peter Galbavy
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This product includes software developed by Peter Galbavy
48 * 4. The name of the author may not be used to endorse or promote products
49 * derived from this software without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
52 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
54 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
55 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
57 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
60 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61 * POSSIBILITY OF SUCH DAMAGE.
65 * Based on aic6360 by Jarle Greipsland
67 * Acknowledgements: Many of the algorithms used in this driver are
68 * inspired by the work of Julian Elischer (julian@tfs.com) and
69 * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
73 * Initial m68k mac support from Allen Briggs <briggs@macbsd.com>
74 * (basically consisting of the match, a bit of the attach, and the
75 * "DMA" glue functions).
79 * Copyright (c) 1997 Eric S. Hvozda (hvozda@netcom.com)
80 * All rights reserved.
82 * Redistribution and use in source and binary forms, with or without
83 * modification, are permitted provided that the following conditions
85 * 1. Redistributions of source code must retain the above copyright
86 * notice, this list of conditions and the following disclaimer.
87 * 2. Redistributions in binary form must reproduce the above copyright
88 * notice, this list of conditions and the following disclaimer in the
89 * documentation and/or other materials provided with the distribution.
90 * 3. All advertising materials mentioning features or use of this software
91 * must display the following acknowledgement:
92 * This product includes software developed by Eric S. Hvozda.
93 * 4. The name of Eric S. Hvozda may not be used to endorse or promote products
94 * derived from this software without specific prior written permission.
96 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
97 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
98 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
99 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
100 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
101 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
102 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
103 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
104 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
105 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
108 #include <sys/cdefs.h>
109 __KERNEL_RCSID(0, "$NetBSD: esp_isa.c,v 1.35 2008/04/13 04:55:53 tsutsui Exp $");
111 #include <sys/param.h>
112 #include <sys/systm.h>
113 #include <sys/device.h>
117 #include <sys/intr.h>
119 #include <dev/scsipi/scsipi_all.h>
120 #include <dev/scsipi/scsi_all.h>
121 #include <dev/scsipi/scsiconf.h>
123 #include <dev/isa/isavar.h>
124 #include <dev/isa/isadmavar.h>
126 #include <dev/ic/ncr53c9xreg.h>
127 #include <dev/ic/ncr53c9xvar.h>
129 #include <dev/isa/esp_isavar.h>
131 int esp_isa_match(device_t
, cfdata_t
, void *);
132 void esp_isa_attach(device_t
, device_t
, void *);
134 CFATTACH_DECL_NEW(esp_isa
, sizeof(struct esp_isa_softc
),
135 esp_isa_match
, esp_isa_attach
, NULL
, NULL
);
137 int esp_isa_debug
= 0; /* ESP_SHOWTRAC | ESP_SHOWREGS | ESP_SHOWMISC */
140 * Functions and the switch for the MI code.
142 uint8_t esp_isa_read_reg(struct ncr53c9x_softc
*, int);
143 void esp_isa_write_reg(struct ncr53c9x_softc
*, int, uint8_t);
144 int esp_isa_dma_isintr(struct ncr53c9x_softc
*);
145 void esp_isa_dma_reset(struct ncr53c9x_softc
*);
146 int esp_isa_dma_intr(struct ncr53c9x_softc
*);
147 int esp_isa_dma_setup(struct ncr53c9x_softc
*, uint8_t **,
148 size_t *, int, size_t *);
149 void esp_isa_dma_go(struct ncr53c9x_softc
*);
150 void esp_isa_dma_stop(struct ncr53c9x_softc
*);
151 int esp_isa_dma_isactive(struct ncr53c9x_softc
*);
153 struct ncr53c9x_glue esp_isa_glue
= {
162 esp_isa_dma_isactive
,
163 NULL
, /* gl_clear_latched_intr */
170 esp_isa_find(bus_space_tag_t iot
, bus_space_handle_t ioh
,
171 struct esp_isa_probe_data
*epd
)
178 ESP_TRACE(("[esp_isa_find] "));
180 /* reset card before we probe? */
182 epd
->sc_cfg4
= NCRCFG4_ACTNEG
;
183 epd
->sc_cfg5
= NCRCFG5_CRS1
| NCRCFG5_AADDR
| NCRCFG5_PTRINC
;
186 * Switch to the PIO regs and look for the bit pattern
189 bus_space_write_1(iot
, ioh
, NCR_CFG5
, epd
->sc_cfg5
);
191 #define SIG_MASK 0x87
192 #define REV_MASK 0x70
196 #define ISESP406 0x40
198 vers
= bus_space_read_1(iot
, ioh
, NCR_SIGNTR
);
199 p1
= bus_space_read_1(iot
, ioh
, NCR_SIGNTR
) & SIG_MASK
;
200 p2
= bus_space_read_1(iot
, ioh
, NCR_SIGNTR
) & SIG_MASK
;
202 ESP_MISC(("esp_isa_find: 0x%0x 0x%0x 0x%0x\n", vers
, p1
, p2
));
204 if (!((p1
== M1
&& p2
== M2
) || (p1
== M2
&& p2
== M1
)))
207 /* Ok, what is it? */
208 epd
->sc_isncr
= (vers
& ISNCR
);
209 epd
->sc_rev
= ((vers
& REV_MASK
) == ISESP406
) ?
210 NCR_VARIANT_ESP406
: NCR_VARIANT_FAS408
;
212 /* What do the jumpers tell us? */
213 jmp
= bus_space_read_1(iot
, ioh
, NCR_JMP
);
215 epd
->sc_msize
= (jmp
& NCRJMP_ROMSZ
) ? 0x4000 : 0x8000;
216 epd
->sc_parity
= jmp
& NCRJMP_J2
;
217 epd
->sc_sync
= jmp
& NCRJMP_J4
;
218 epd
->sc_id
= (jmp
& NCRJMP_J3
) ? 7 : 6;
219 switch (jmp
& (NCRJMP_J0
| NCRJMP_J1
)) {
220 case NCRJMP_J0
| NCRJMP_J1
:
234 bus_space_write_1(iot
, ioh
, NCR_CFG5
, epd
->sc_cfg5
);
236 /* Try to set NCRESPCFG3_FCLK, some FAS408's don't support
237 * NCRESPCFG3_FCLK even though it is documented. A bad
238 * batch of chips perhaps?
240 bus_space_write_1(iot
, ioh
, NCR_ESPCFG3
,
241 bus_space_read_1(iot
, ioh
, NCR_ESPCFG3
) | NCRESPCFG3_FCLK
);
242 epd
->sc_isfast
= bus_space_read_1(iot
, ioh
, NCR_ESPCFG3
)
249 esp_isa_init(struct esp_isa_softc
*esc
, struct esp_isa_probe_data
*epd
)
251 struct ncr53c9x_softc
*sc
= &esc
->sc_ncr53c9x
;
253 ESP_TRACE(("[esp_isa_init] "));
256 * Set up the glue for MI code early; we use some of it here.
258 sc
->sc_glue
= &esp_isa_glue
;
260 sc
->sc_rev
= epd
->sc_rev
;
261 sc
->sc_id
= epd
->sc_id
;
263 /* If we could set NCRESPCFG3_FCLK earlier, we can really move */
264 sc
->sc_cfg3
= NCR_READ_REG(sc
, NCR_ESPCFG3
);
265 if ((epd
->sc_rev
== NCR_VARIANT_FAS408
) && epd
->sc_isfast
) {
267 sc
->sc_cfg3
|= NCRESPCFG3_FCLK
;
271 /* Setup the register defaults */
272 sc
->sc_cfg1
= sc
->sc_id
;
274 sc
->sc_cfg1
|= NCRCFG1_PARENB
;
275 sc
->sc_cfg2
= NCRCFG2_SCSI2
;
276 sc
->sc_cfg3
|= NCRESPCFG3_IDM
| NCRESPCFG3_FSCSI
;
277 sc
->sc_cfg4
= epd
->sc_cfg4
;
278 sc
->sc_cfg5
= epd
->sc_cfg5
;
281 * This is the value used to start sync negotiations
282 * Note that the NCR register "SYNCTP" is programmed
283 * in "clocks per byte", and has a minimum value of 4.
284 * The SCSI period used in negotiation is one-fourth
285 * of the time (in nanoseconds) needed to transfer one byte.
286 * Since the chip's clock is given in MHz, we have the following
287 * formula: 4 * period = (1000 / freq) * 4
291 aprint_normal_dev(sc
->sc_dev
,
292 "sync requested, but not supported; will do async\n");
299 /* Really no limit, but since we want to fit into the TCR... */
300 sc
->sc_maxxfer
= 64 * 1024;
304 * Check the slots looking for a board we recognise
305 * If we find one, note it's address (slot) and call
306 * the actual probe routine to check it out.
309 esp_isa_match(device_t parent
, cfdata_t cf
, void *aux
)
311 struct isa_attach_args
*ia
= aux
;
312 bus_space_tag_t iot
= ia
->ia_iot
;
313 bus_space_handle_t ioh
;
314 struct esp_isa_probe_data epd
;
324 if (ISA_DIRECT_CONFIG(ia
))
327 ESP_TRACE(("[esp_isa_match] "));
329 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
332 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, ESP_ISA_IOSIZE
, 0, &ioh
))
335 rv
= esp_isa_find(iot
, ioh
, &epd
);
337 bus_space_unmap(iot
, ioh
, ESP_ISA_IOSIZE
);
340 if (ia
->ia_irq
[0].ir_irq
!= ISA_UNKNOWN_IRQ
&&
341 ia
->ia_irq
[0].ir_irq
!= epd
.sc_irq
) {
343 printf("%s: configured IRQ (%0d) does not "
344 "match board IRQ (%0d), device not configured\n",
345 __func__
, ia
->ia_irq
[0].ir_irq
, epd
.sc_irq
);
349 ia
->ia_irq
[0].ir_irq
= epd
.sc_irq
;
350 ia
->ia_iomem
[0].ir_size
= 0;
351 ia
->ia_io
[0].ir_size
= ESP_ISA_IOSIZE
;
357 * Attach this instance, and then all the sub-devices
360 esp_isa_attach(device_t parent
, device_t self
, void *aux
)
362 struct esp_isa_softc
*esc
= device_private(self
);
363 struct ncr53c9x_softc
*sc
= &esc
->sc_ncr53c9x
;
364 struct isa_attach_args
*ia
= aux
;
365 bus_space_tag_t iot
= ia
->ia_iot
;
366 bus_space_handle_t ioh
;
367 struct esp_isa_probe_data epd
;
368 isa_chipset_tag_t ic
= ia
->ia_ic
;
373 ESP_TRACE(("[esp_isa_attach] "));
375 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, ESP_ISA_IOSIZE
, 0, &ioh
)) {
376 aprint_error_dev(self
, "can't map i/o space\n");
380 if (!esp_isa_find(iot
, ioh
, &epd
)) {
381 aprint_error_dev(self
, "esp_isa_find failed\n");
385 if (ia
->ia_drq
[0].ir_drq
!= ISA_UNKNOWN_DRQ
) {
386 if ((error
= isa_dmacascade(ic
, ia
->ia_drq
[0].ir_drq
)) != 0) {
387 aprint_error_dev(self
,
388 "unable to cascade DRQ, error = %d\n", error
);
393 esc
->sc_ih
= isa_intr_establish(ic
, ia
->ia_irq
[0].ir_irq
, IST_EDGE
,
394 IPL_BIO
, ncr53c9x_intr
, esc
);
395 if (esc
->sc_ih
== NULL
) {
396 aprint_error_dev(self
, "couldn't establish interrupt\n");
402 esp_isa_init(esc
, &epd
);
404 aprint_normal_dev(self
, "%ssync,%sparity\n",
405 epd
.sc_sync
? " " : " no ", epd
.sc_parity
? " " : " no ");
406 aprint_normal("%s", device_xname(self
));
409 * Now try to attach all the sub-devices
411 sc
->sc_adapter
.adapt_minphys
= minphys
;
412 sc
->sc_adapter
.adapt_request
= ncr53c9x_scsipi_request
;
420 esp_isa_read_reg(struct ncr53c9x_softc
*sc
, int reg
)
422 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
425 v
= bus_space_read_1(esc
->sc_iot
, esc
->sc_ioh
, reg
);
427 ESP_REGS(("[esp_isa_read_reg CRS%c 0x%02x=0x%02x] ",
428 (bus_space_read_1(esc
->sc_iot
, esc
->sc_ioh
, NCR_CFG4
) &
429 NCRCFG4_CRS1
) ? '1' : '0', reg
, v
));
435 esp_isa_write_reg(struct ncr53c9x_softc
*sc
, int reg
, uint8_t val
)
437 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
440 if (reg
== NCR_CMD
&& v
== (NCRCMD_TRANS
|NCRCMD_DMA
)) {
444 ESP_REGS(("[esp_isa_write_reg CRS%c 0x%02x=0x%02x] ",
445 (bus_space_read_1(esc
->sc_iot
, esc
->sc_ioh
, NCR_CFG4
) &
446 NCRCFG4_CRS1
) ? '1' : '0', reg
, v
));
448 bus_space_write_1(esc
->sc_iot
, esc
->sc_ioh
, reg
, v
);
452 esp_isa_dma_isintr(struct ncr53c9x_softc
*sc
)
455 ESP_TRACE(("[esp_isa_dma_isintr] "));
457 return NCR_READ_REG(sc
, NCR_STAT
) & NCRSTAT_INT
;
461 esp_isa_dma_reset(struct ncr53c9x_softc
*sc
)
463 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
465 ESP_TRACE(("[esp_isa_dma_reset] "));
472 esp_isa_dma_intr(struct ncr53c9x_softc
*sc
)
474 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
476 u_int espphase
, espstat
, espintr
;
479 ESP_TRACE(("[esp_isa_dma_intr] "));
481 if (esc
->sc_active
== 0) {
482 printf("%s: dma_intr--inactive DMA\n",
483 device_xname(sc
->sc_dev
));
487 if ((sc
->sc_espintr
& NCRINTR_BS
) == 0) {
492 cnt
= *esc
->sc_pdmalen
;
493 if (*esc
->sc_pdmalen
== 0) {
494 printf("%s: data interrupt, but no count left\n",
495 device_xname(sc
->sc_dev
));
498 p
= *esc
->sc_dmaaddr
;
499 espphase
= sc
->sc_phase
;
500 espstat
= (u_int
)sc
->sc_espstat
;
501 espintr
= (u_int
)sc
->sc_espintr
;
503 if (esc
->sc_datain
) {
504 *p
++ = NCR_READ_REG(sc
, NCR_FIFO
);
506 if (espphase
== DATA_IN_PHASE
) {
507 NCR_WRITE_REG(sc
, NCR_CMD
, NCRCMD_TRANS
);
512 if ((espphase
== DATA_OUT_PHASE
) ||
513 (espphase
== MESSAGE_OUT_PHASE
)) {
514 NCR_WRITE_REG(sc
, NCR_FIFO
, *p
++);
516 NCR_WRITE_REG(sc
, NCR_CMD
, NCRCMD_TRANS
);
522 if (esc
->sc_active
) {
523 while ((NCR_READ_REG(sc
, NCR_STAT
) & NCRSTAT_INT
) == 0)
525 espstat
= NCR_READ_REG(sc
, NCR_STAT
);
526 espintr
= NCR_READ_REG(sc
, NCR_INTR
);
527 espphase
= (espintr
& NCRINTR_DIS
) ?
528 /* Disconnected */ BUSFREE_PHASE
:
529 espstat
& PHASE_MASK
;
531 } while (esc
->sc_active
&& espintr
);
532 sc
->sc_phase
= espphase
;
533 sc
->sc_espstat
= (uint8_t)espstat
;
534 sc
->sc_espintr
= (uint8_t)espintr
;
535 *esc
->sc_dmaaddr
= p
;
536 *esc
->sc_pdmalen
= cnt
;
538 if (*esc
->sc_pdmalen
== 0) {
539 esc
->sc_tc
= NCRSTAT_TC
;
541 sc
->sc_espstat
|= esc
->sc_tc
;
546 esp_isa_dma_setup(struct ncr53c9x_softc
*sc
, uint8_t **addr
, size_t *len
,
547 int datain
, size_t *dmasize
)
549 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
551 ESP_TRACE(("[esp_isa_dma_setup] "));
553 esc
->sc_dmaaddr
= addr
;
554 esc
->sc_pdmalen
= len
;
555 esc
->sc_datain
= datain
;
556 esc
->sc_dmasize
= *dmasize
;
563 esp_isa_dma_go(struct ncr53c9x_softc
*sc
)
565 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
567 ESP_TRACE(("[esp_isa_dma_go] "));
573 esp_isa_dma_stop(struct ncr53c9x_softc
*sc
)
575 ESP_TRACE(("[esp_isa_dma_stop] "));
579 esp_isa_dma_isactive(struct ncr53c9x_softc
*sc
)
581 struct esp_isa_softc
*esc
= (struct esp_isa_softc
*)sc
;
583 ESP_TRACE(("[esp_isa_dma_isactive] "));
585 return esc
->sc_active
;