1 /* $NetBSD: nca_isa.c,v 1.20 2008/04/04 16:19:51 tsutsui Exp $ */
4 * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by John M. Ruschmeyer.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * FreeBSD generic NCR-5380/NCR-53C400 SCSI driver
35 * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru)
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.
46 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPERS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 #include <sys/cdefs.h>
60 __KERNEL_RCSID(0, "$NetBSD: nca_isa.c,v 1.20 2008/04/04 16:19:51 tsutsui Exp $");
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/device.h>
70 #include <dev/scsipi/scsi_all.h>
71 #include <dev/scsipi/scsipi_all.h>
72 #include <dev/scsipi/scsiconf.h>
74 #include <dev/isa/isavar.h>
75 #include <dev/isa/isadmavar.h>
77 #include <dev/ic/ncr5380reg.h>
78 #include <dev/ic/ncr5380var.h>
79 #include <dev/ic/ncr53c400reg.h>
81 struct nca_isa_softc
{
82 struct ncr5380_softc sc_ncr5380
; /* glue to MI code */
89 struct nca_isa_probe_data
{
95 int nca_isa_find(bus_space_tag_t
, bus_space_handle_t
, bus_size_t
,
96 struct nca_isa_probe_data
*);
97 int nca_isa_match(device_t
, cfdata_t
, void *);
98 void nca_isa_attach(device_t
, device_t
, void *);
99 int nca_isa_test(bus_space_tag_t
, bus_space_handle_t
, bus_size_t
);
101 CFATTACH_DECL_NEW(nca_isa
, sizeof(struct nca_isa_softc
),
102 nca_isa_match
, nca_isa_attach
, NULL
, NULL
);
105 /* Supported controller types */
106 #define MAX_NCA_CONTROLLER 3
107 #define CTLR_NCR_5380 1
108 #define CTLR_NCR_53C400 2
111 #define NCA_ISA_IOSIZE 16
112 #define MIN_DMA_LEN 128
114 /* Options for disconnect/reselect, DMA, and interrupts. */
115 #define NCA_NO_DISCONNECT 0xff
116 #define NCA_NO_PARITY_CHK 0xff00
117 #define NCA_FORCE_POLLING 0x10000
121 * Initialization and test function used by nca_isa_find()
124 nca_isa_test(bus_space_tag_t iot
, bus_space_handle_t ioh
, bus_size_t reg_offset
)
127 /* Reset the SCSI bus. */
128 bus_space_write_1(iot
, ioh
, reg_offset
+ C80_ICR
, SCI_ICMD_RST
);
129 bus_space_write_1(iot
, ioh
, reg_offset
+ C80_ODR
, 0);
130 /* Hold reset for at least 25 microseconds. */
132 /* Check that status cleared. */
133 if (bus_space_read_1(iot
, ioh
, reg_offset
+ C80_CSBR
) != SCI_BUS_RST
) {
135 printf("%s: reset status not cleared [0x%x]\n",
136 __func__
, bus_space_read_1(iot
, ioh
, reg_offset
+C80_CSBR
));
138 bus_space_write_1(iot
, ioh
, reg_offset
+C80_ICR
, 0);
142 bus_space_write_1(iot
, ioh
, reg_offset
+ C80_ICR
, 0);
143 /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
146 /* Read RPI port, resetting parity/interrupt state. */
147 bus_space_read_1(iot
, ioh
, reg_offset
+ C80_RPIR
);
149 /* Test BSR: parity error, interrupt request and busy loss state
150 * should be cleared. */
151 if (bus_space_read_1(iot
, ioh
, reg_offset
+ C80_BSR
) & (SCI_CSR_PERR
|
152 SCI_CSR_INT
| SCI_CSR_DISC
)) {
154 printf("%s: Parity/Interrupt/Busy not cleared [0x%x]\n",
155 __func__
, bus_space_read_1(iot
, ioh
, reg_offset
+C80_BSR
));
160 /* We must have found one */
169 nca_isa_find(bus_space_tag_t iot
, bus_space_handle_t ioh
,
170 bus_size_t max_offset
, struct nca_isa_probe_data
*epd
)
173 * We check for the existence of a board by trying to initialize it,
174 * Then sending the commands to reset the SCSI bus.
175 * (Unfortunately, this duplicates code which is already in the MI
176 * driver. Unavoidable as that code is not suited to this task.)
177 * This is largely stolen from FreeBSD.
180 bus_size_t base_offset
, reg_offset
= 0;
184 * In the case of a port-mapped board, we should be pointing
185 * right at the chip registers (if they are there at all).
186 * For a memory-mapped card, we loop through the 16K paragraph,
187 * 8 bytes at a time, until we either find it or run out
188 * of region. This means we will probably be doing things like
189 * trying to write to ROMS, etc. Hopefully, this is not a problem.
192 for (base_offset
= 0; base_offset
< max_offset
; base_offset
+= 0x08) {
194 printf("%s: testing offset 0x%x\n", __func__
, (int)base_offset
);
197 /* See if anything is there */
198 if (bus_space_read_1(iot
, ioh
, base_offset
) == 0xff)
201 /* Loop around for each board type */
202 for (cont_type
= 1; cont_type
<= MAX_NCA_CONTROLLER
;
204 /* Per-controller initialization */
207 /* No special inits */
210 case CTLR_NCR_53C400
:
211 /* Reset into 5380-compat. mode */
212 bus_space_write_1(iot
, ioh
,
213 base_offset
+ C400_CSR
,
214 C400_CSR_5380_ENABLE
);
215 reg_offset
= C400_5380_REG_OFFSET
;
218 /* Not currently supported */
224 /* Initialize controller and bus */
225 if (nca_isa_test(iot
, ioh
, base_offset
+reg_offset
)) {
226 epd
->sc_reg_offset
= base_offset
;
227 epd
->sc_host_type
= cont_type
;
228 return cont_type
; /* This must be it */
233 /* If we got here, we didn't find one */
239 * See if there is anything at the config'd address.
240 * If so, call the real probe to see what it is.
243 nca_isa_match(device_t parent
, cfdata_t cf
, void *aux
)
245 struct isa_attach_args
*ia
= aux
;
246 bus_space_tag_t iot
= ia
->ia_iot
;
247 bus_space_tag_t memt
= ia
->ia_memt
;
248 bus_space_handle_t ioh
;
249 struct nca_isa_probe_data epd
;
252 if (ISA_DIRECT_CONFIG(ia
))
255 /* See if we are looking for a port- or memory-mapped adapter */
256 if (ia
->ia_nio
> 0 || ia
->ia_io
[0].ir_addr
!= ISA_UNKNOWN_PORT
) {
257 /* Port-mapped card */
258 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, NCA_ISA_IOSIZE
,
262 /* See if a 53C80/53C400 is there */
263 rv
= nca_isa_find(iot
, ioh
, 0x07, &epd
);
265 bus_space_unmap(iot
, ioh
, NCA_ISA_IOSIZE
);
269 ia
->ia_io
[0].ir_size
= NCA_ISA_IOSIZE
;
274 } else if (ia
->ia_niomem
> 0) {
275 /* Memory-mapped card */
276 if (bus_space_map(memt
, ia
->ia_iomem
[0].ir_addr
, 0x4000,
280 /* See if a 53C80/53C400 is somewhere in this para. */
281 rv
= nca_isa_find(memt
, ioh
, 0x03ff0, &epd
);
283 bus_space_unmap(memt
, ioh
, 0x04000);
287 ia
->ia_iomem
[0].ir_addr
+= epd
.sc_reg_offset
;
288 ia
->ia_iomem
[0].ir_size
= NCA_ISA_IOSIZE
;
299 * Attach this instance, and then all the sub-devices
302 nca_isa_attach(device_t parent
, device_t self
, void *aux
)
304 struct nca_isa_softc
*esc
= device_private(self
);
305 struct ncr5380_softc
*sc
= &esc
->sc_ncr5380
;
306 struct isa_attach_args
*ia
= aux
;
307 bus_space_tag_t iot
= ia
->ia_iot
;
308 bus_space_handle_t ioh
;
309 struct nca_isa_probe_data epd
;
310 isa_chipset_tag_t ic
= ia
->ia_ic
;
315 if (ia
->ia_nio
> 0) {
317 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, NCA_ISA_IOSIZE
,
319 aprint_error_dev(self
, "can't map i/o space\n");
323 KASSERT(ia
->ia_niomem
> 0);
325 if (bus_space_map(iot
, ia
->ia_iomem
[0].ir_addr
, NCA_ISA_IOSIZE
,
327 aprint_error_dev(self
, "can't map mem space\n");
332 switch (nca_isa_find(iot
, ioh
, NCA_ISA_IOSIZE
, &epd
)) {
334 /* Not found- must have gone away */
335 aprint_error_dev(self
, "nca_isa_find failed\n");
338 aprint_normal_dev(self
, "NCR 53C80 detected\n");
347 sc
->sc_rev
= NCR_VARIANT_NCR5380
;
349 case CTLR_NCR_53C400
:
350 aprint_normal_dev(self
, "NCR 53C400 detected\n");
351 sc
->sci_r0
= C400_5380_REG_OFFSET
+ 0;
352 sc
->sci_r1
= C400_5380_REG_OFFSET
+ 1;
353 sc
->sci_r2
= C400_5380_REG_OFFSET
+ 2;
354 sc
->sci_r3
= C400_5380_REG_OFFSET
+ 3;
355 sc
->sci_r4
= C400_5380_REG_OFFSET
+ 4;
356 sc
->sci_r5
= C400_5380_REG_OFFSET
+ 5;
357 sc
->sci_r6
= C400_5380_REG_OFFSET
+ 6;
358 sc
->sci_r7
= C400_5380_REG_OFFSET
+ 7;
359 sc
->sc_rev
= NCR_VARIANT_NCR53C400
;
362 aprint_normal_dev(self
, "ProAudio Spectrum 16 detected\n");
363 sc
->sc_rev
= NCR_VARIANT_PAS16
;
368 * MD function pointers used by the MI code.
370 sc
->sc_pio_out
= ncr5380_pio_out
;
371 sc
->sc_pio_in
= ncr5380_pio_in
;
372 sc
->sc_dma_alloc
= NULL
;
373 sc
->sc_dma_free
= NULL
;
374 sc
->sc_dma_setup
= NULL
;
375 sc
->sc_dma_start
= NULL
;
376 sc
->sc_dma_poll
= NULL
;
377 sc
->sc_dma_eop
= NULL
;
378 sc
->sc_dma_stop
= NULL
;
379 sc
->sc_intr_on
= NULL
;
380 sc
->sc_intr_off
= NULL
;
382 if (ia
->ia_nirq
> 0 && ia
->ia_irq
[0].ir_irq
!= ISA_UNKNOWN_IRQ
) {
383 esc
->sc_ih
= isa_intr_establish(ic
, ia
->ia_irq
[0].ir_irq
,
384 IST_EDGE
, IPL_BIO
, ncr5380_intr
, esc
);
385 if (esc
->sc_ih
== NULL
) {
386 aprint_error_dev(self
,
387 "couldn't establish interrupt\n");
391 sc
->sc_flags
|= NCR5380_FORCE_POLLING
;
395 * Support the "options" (config file flags).
396 * Disconnect/reselect is a per-target mask.
397 * Interrupts and DMA are per-controller.
400 esc
->sc_options
= 0x00000; /* no options */
402 esc
->sc_options
= 0x0ffff; /* all options except force poll */
405 sc
->sc_no_disconnect
= (esc
->sc_options
& NCA_NO_DISCONNECT
);
406 sc
->sc_parity_disable
= (esc
->sc_options
& NCA_NO_PARITY_CHK
) >> 8;
407 if (esc
->sc_options
& NCA_FORCE_POLLING
)
408 sc
->sc_flags
|= NCR5380_FORCE_POLLING
;
409 sc
->sc_min_dma_len
= MIN_DMA_LEN
;
413 * Initialize fields used by the MI code
419 * Fill in our portion of the scsipi_adapter.
421 sc
->sc_adapter
.adapt_request
= ncr5380_scsipi_request
;
422 sc
->sc_adapter
.adapt_minphys
= minphys
;
425 * Fill in our portion of the scsipi_channel.
428 sc
->sc_channel
.chan_id
= 7;
431 * Initialize nca board itself.