1 /* $NetBSD: nca_pcmcia.c,v 1.23 2008/04/04 16:19:51 tsutsui Exp $ */
4 * Copyright (c) 2000, 2004 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
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.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: nca_pcmcia.c,v 1.23 2008/04/04 16:19:51 tsutsui Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
43 #include <dev/scsipi/scsi_all.h>
44 #include <dev/scsipi/scsipi_all.h>
45 #include <dev/scsipi/scsiconf.h>
47 #include <dev/pcmcia/pcmciareg.h>
48 #include <dev/pcmcia/pcmciavar.h>
49 #include <dev/pcmcia/pcmciadevs.h>
51 #include <dev/ic/ncr5380reg.h>
52 #include <dev/ic/ncr5380var.h>
53 #include <dev/ic/ncr53c400reg.h>
55 struct nca_pcmcia_softc
{
56 struct ncr5380_softc sc_ncr5380
; /* glue to MI code */
58 /* PCMCIA-specific goo. */
59 struct pcmcia_function
*sc_pf
; /* our PCMCIA function */
60 void *sc_ih
; /* interrupt handler */
63 #define NCA_PCMCIA_ATTACHED 3
66 int nca_pcmcia_match(device_t
, cfdata_t
, void *);
67 int nca_pcmcia_validate_config(struct pcmcia_config_entry
*);
68 void nca_pcmcia_attach(device_t
, device_t
, void *);
69 int nca_pcmcia_detach(device_t
, int);
70 int nca_pcmcia_enable(device_t
, int);
72 CFATTACH_DECL_NEW(nca_pcmcia
, sizeof(struct nca_pcmcia_softc
),
73 nca_pcmcia_match
, nca_pcmcia_attach
, nca_pcmcia_detach
, NULL
);
75 #define MIN_DMA_LEN 128
77 /* Options for disconnect/reselect, DMA, and interrupts. */
78 #define NCA_NO_DISCONNECT 0x00ff
79 #define NCA_NO_PARITY_CHK 0xff00
81 const struct pcmcia_product nca_pcmcia_products
[] = {
82 { PCMCIA_VENDOR_INVALID
, PCMCIA_PRODUCT_INVALID
,
85 const size_t nca_pcmcia_nproducts
=
86 __arraycount(nca_pcmcia_products
);
89 nca_pcmcia_match(device_t parent
, cfdata_t cf
, void *aux
)
91 struct pcmcia_attach_args
*pa
= aux
;
93 if (pcmcia_product_lookup(pa
, nca_pcmcia_products
, nca_pcmcia_nproducts
,
94 sizeof(nca_pcmcia_products
[0]), NULL
))
100 nca_pcmcia_validate_config(struct pcmcia_config_entry
*cfe
)
103 if (cfe
->iftype
!= PCMCIA_IFTYPE_IO
||
104 cfe
->num_memspace
!= 0 ||
105 cfe
->num_iospace
!= 1)
111 nca_pcmcia_attach(device_t parent
, device_t self
, void *aux
)
113 struct nca_pcmcia_softc
*esc
= device_private(self
);
114 struct ncr5380_softc
*sc
= &esc
->sc_ncr5380
;
115 struct pcmcia_attach_args
*pa
= aux
;
116 struct pcmcia_config_entry
*cfe
;
117 struct pcmcia_function
*pf
= pa
->pf
;
124 error
= pcmcia_function_configure(pf
, nca_pcmcia_validate_config
);
126 aprint_error_dev(self
, "configure failed, error=%d\n", error
);
131 sc
->sc_regt
= cfe
->iospace
[0].handle
.iot
;
132 sc
->sc_regh
= cfe
->iospace
[0].handle
.ioh
;
134 /* Initialize 5380 compatible register offsets. */
135 sc
->sci_r0
= C400_5380_REG_OFFSET
+ 0;
136 sc
->sci_r1
= C400_5380_REG_OFFSET
+ 1;
137 sc
->sci_r2
= C400_5380_REG_OFFSET
+ 2;
138 sc
->sci_r3
= C400_5380_REG_OFFSET
+ 3;
139 sc
->sci_r4
= C400_5380_REG_OFFSET
+ 4;
140 sc
->sci_r5
= C400_5380_REG_OFFSET
+ 5;
141 sc
->sci_r6
= C400_5380_REG_OFFSET
+ 6;
142 sc
->sci_r7
= C400_5380_REG_OFFSET
+ 7;
144 sc
->sc_rev
= NCR_VARIANT_NCR53C400
;
147 * MD function pointers used by the MI code.
149 sc
->sc_pio_out
= ncr5380_pio_out
;
150 sc
->sc_pio_in
= ncr5380_pio_in
;
151 sc
->sc_dma_alloc
= NULL
;
152 sc
->sc_dma_free
= NULL
;
153 sc
->sc_dma_setup
= NULL
;
154 sc
->sc_dma_start
= NULL
;
155 sc
->sc_dma_poll
= NULL
;
156 sc
->sc_dma_eop
= NULL
;
157 sc
->sc_dma_stop
= NULL
;
158 sc
->sc_intr_on
= NULL
;
159 sc
->sc_intr_off
= NULL
;
162 * Support the "options" (config file flags).
163 * Disconnect/reselect is a per-target mask.
164 * Interrupts and DMA are per-controller.
167 flags
= 0x0000; /* no options */
169 flags
= 0xffff; /* all options except force poll */
172 sc
->sc_no_disconnect
= (flags
& NCA_NO_DISCONNECT
);
173 sc
->sc_parity_disable
= (flags
& NCA_NO_PARITY_CHK
) >> 8;
174 sc
->sc_min_dma_len
= MIN_DMA_LEN
;
176 error
= nca_pcmcia_enable(self
, 1);
180 sc
->sc_adapter
.adapt_enable
= nca_pcmcia_enable
;
181 sc
->sc_adapter
.adapt_refcnt
= 1;
184 scsipi_adapter_delref(&sc
->sc_adapter
);
185 esc
->sc_state
= NCA_PCMCIA_ATTACHED
;
189 pcmcia_function_unconfigure(pf
);
193 nca_pcmcia_detach(device_t self
, int flags
)
195 struct nca_pcmcia_softc
*sc
= device_private(self
);
198 if (sc
->sc_state
!= NCA_PCMCIA_ATTACHED
)
201 error
= ncr5380_detach(&sc
->sc_ncr5380
, flags
);
205 pcmcia_function_unconfigure(sc
->sc_pf
);
211 nca_pcmcia_enable(device_t self
, int onoff
)
213 struct nca_pcmcia_softc
*sc
= device_private(self
);
217 /* Establish the interrupt handler. */
218 sc
->sc_ih
= pcmcia_intr_establish(sc
->sc_pf
, IPL_BIO
,
219 ncr5380_intr
, &sc
->sc_ncr5380
);
220 if (sc
->sc_ih
== NULL
)
223 error
= pcmcia_function_enable(sc
->sc_pf
);
225 pcmcia_intr_disestablish(sc
->sc_pf
, sc
->sc_ih
);
230 /* Initialize only chip. */
231 ncr5380_init(&sc
->sc_ncr5380
);
233 pcmcia_function_disable(sc
->sc_pf
);
234 pcmcia_intr_disestablish(sc
->sc_pf
, sc
->sc_ih
);