1 /* $NetBSD: ciss_pci.c,v 1.8 2009/05/12 08:23:00 cegger Exp $ */
2 /* $OpenBSD: ciss_pci.c,v 1.9 2005/12/13 15:56:01 brad Exp $ */
5 * Copyright (c) 2005 Michael Shalayeff
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
17 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
18 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/cdefs.h>
22 __KERNEL_RCSID(0, "$NetBSD: ciss_pci.c,v 1.8 2009/05/12 08:23:00 cegger Exp $");
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/kernel.h>
27 #include <sys/malloc.h>
28 #include <sys/device.h>
30 #include <dev/pci/pcidevs.h>
31 #include <dev/pci/pcivar.h>
35 #include <dev/scsipi/scsipi_all.h>
36 #include <dev/scsipi/scsipi_disk.h>
37 #include <dev/scsipi/scsipiconf.h>
39 #include <dev/ic/cissreg.h>
40 #include <dev/ic/cissvar.h>
44 int ciss_pci_match(device_t
, cfdata_t
, void *);
45 void ciss_pci_attach(device_t
, device_t
, void *);
47 CFATTACH_DECL(ciss_pci
, sizeof(struct ciss_softc
),
48 ciss_pci_match
, ciss_pci_attach
, NULL
, NULL
);
54 } ciss_pci_devices
[] = {
57 PCI_PRODUCT_COMPAQ_CSA532
,
58 "Compaq Smart Array 532"
62 PCI_PRODUCT_COMPAQ_CSA5300
,
63 "Compaq Smart Array 5300 V1"
67 PCI_PRODUCT_COMPAQ_CSA5300_2
,
68 "Compaq Smart Array 5300 V2"
72 PCI_PRODUCT_COMPAQ_CSA5312
,
73 "Compaq Smart Array 5312"
77 PCI_PRODUCT_COMPAQ_CSA5i
,
78 "Compaq Smart Array 5i"
82 PCI_PRODUCT_COMPAQ_CSA5i_2
,
83 "Compaq Smart Array 5i V2"
87 PCI_PRODUCT_COMPAQ_CSA6i
,
88 "Compaq Smart Array 6i"
92 PCI_PRODUCT_COMPAQ_CSA641
,
93 "Compaq Smart Array 641"
97 PCI_PRODUCT_COMPAQ_CSA642
,
98 "Compaq Smart Array 642"
102 PCI_PRODUCT_COMPAQ_CSA6400
,
103 "Compaq Smart Array 6400"
107 PCI_PRODUCT_COMPAQ_CSA6400EM
,
108 "Compaq Smart Array 6400EM"
112 PCI_PRODUCT_COMPAQ_CSA6422
,
113 "Compaq Smart Array 6422"
117 PCI_PRODUCT_COMPAQ_CSA64XX
,
118 "Compaq Smart Array 64XX"
122 PCI_PRODUCT_HP_HPSAE200
,
127 PCI_PRODUCT_HP_HPSAE200I_1
,
128 "HP Smart Array E200I-1"
132 PCI_PRODUCT_HP_HPSAE200I_2
,
133 "HP Smart Array E200I-2"
137 PCI_PRODUCT_HP_HPSAE200I_3
,
138 "HP Smart Array E200I-3"
142 PCI_PRODUCT_HP_HPSAP600
,
143 "HP Smart Array P600"
147 PCI_PRODUCT_HP_HPSAP800
,
148 "HP Smart Array P800"
152 PCI_PRODUCT_HP_HPSAV100
,
153 "HP Smart Array V100"
157 PCI_PRODUCT_HP_HPSA_1
,
162 PCI_PRODUCT_HP_HPSA_2
,
167 PCI_PRODUCT_HP_HPSA_3
,
172 PCI_PRODUCT_HP_HPSA_4
,
177 PCI_PRODUCT_HP_HPSA_5
,
182 PCI_PRODUCT_HP_HPSA_6
,
187 PCI_PRODUCT_HP_HPSA_7
,
192 PCI_PRODUCT_HP_HPSA_8
,
197 PCI_PRODUCT_HP_HPSA_9
,
202 PCI_PRODUCT_HP_HPSA_10
,
207 PCI_PRODUCT_HP_HPSA_11
,
212 PCI_PRODUCT_HP_HPSA_12
,
217 PCI_PRODUCT_HP_HPSA_13
,
228 ciss_pci_match(device_t parent
, cfdata_t match
, void *aux
)
230 struct pci_attach_args
*pa
= aux
;
231 pcireg_t reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_SUBSYS_ID_REG
);
234 for (i
= 0; ciss_pci_devices
[i
].vendor
; i
++)
236 if ((PCI_VENDOR(pa
->pa_id
) == ciss_pci_devices
[i
].vendor
&&
237 PCI_PRODUCT(pa
->pa_id
) == ciss_pci_devices
[i
].product
) ||
238 (PCI_VENDOR(reg
) == ciss_pci_devices
[i
].vendor
&&
239 PCI_PRODUCT(reg
) == ciss_pci_devices
[i
].product
))
247 ciss_pci_attach(device_t parent
, device_t self
, void *aux
)
249 struct ciss_softc
*sc
= device_private(self
);
250 struct pci_attach_args
*pa
= aux
;
251 bus_size_t size
, cfgsz
;
252 pci_intr_handle_t ih
;
254 int cfg_bar
, memtype
;
255 pcireg_t reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_SUBSYS_ID_REG
);
258 for (i
= 0; ciss_pci_devices
[i
].vendor
; i
++)
260 if ((PCI_VENDOR(pa
->pa_id
) == ciss_pci_devices
[i
].vendor
&&
261 PCI_PRODUCT(pa
->pa_id
) == ciss_pci_devices
[i
].product
) ||
262 (PCI_VENDOR(reg
) == ciss_pci_devices
[i
].vendor
&&
263 PCI_PRODUCT(reg
) == ciss_pci_devices
[i
].product
))
265 printf(": %s\n", ciss_pci_devices
[i
].name
);
270 memtype
= pci_mapreg_type(pa
->pa_pc
, pa
->pa_tag
, CISS_BAR
);
271 if (memtype
!= (PCI_MAPREG_TYPE_MEM
| PCI_MAPREG_MEM_TYPE_32BIT
) &&
272 memtype
!= (PCI_MAPREG_TYPE_MEM
| PCI_MAPREG_MEM_TYPE_64BIT
)) {
273 printf(": wrong BAR type\n");
276 if (pci_mapreg_map(pa
, CISS_BAR
, memtype
, 0,
277 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, &size
)) {
278 printf(": can't map controller i/o space\n");
281 sc
->sc_dmat
= pa
->pa_dmat
;
283 sc
->iem
= CISS_READYENA
;
284 reg
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_SUBSYS_ID_REG
);
285 if (PCI_VENDOR(reg
) == PCI_VENDOR_COMPAQ
&&
286 (PCI_PRODUCT(reg
) == PCI_PRODUCT_COMPAQ_CSA5i
||
287 PCI_PRODUCT(reg
) == PCI_PRODUCT_COMPAQ_CSA532
||
288 PCI_PRODUCT(reg
) == PCI_PRODUCT_COMPAQ_CSA5312
))
289 sc
->iem
= CISS_READYENAB
;
291 cfg_bar
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, CISS_CFG_BAR
);
292 sc
->cfgoff
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CISS_CFG_OFF
);
293 if (cfg_bar
!= CISS_BAR
) {
294 if (pci_mapreg_map(pa
, cfg_bar
, PCI_MAPREG_TYPE_MEM
, 0,
295 NULL
, &sc
->cfg_ioh
, NULL
, &cfgsz
)) {
296 printf(": can't map controller config space\n");
297 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, size
);
301 sc
->cfg_ioh
= sc
->sc_ioh
;
305 if (sc
->cfgoff
+ sizeof(struct ciss_config
) > cfgsz
) {
306 printf(": unfit config space\n");
307 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, size
);
308 if (cfg_bar
!= CISS_BAR
)
309 bus_space_unmap(sc
->sc_iot
, sc
->cfg_ioh
, cfgsz
);
313 /* disable interrupts until ready */
314 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CISS_IMR
,
315 bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CISS_IMR
) | sc
->iem
);
317 if (pci_intr_map(pa
, &ih
)) {
318 printf(": can't map interrupt\n");
319 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, size
);
320 if (cfg_bar
!= CISS_BAR
)
321 bus_space_unmap(sc
->sc_iot
, sc
->cfg_ioh
, cfgsz
);
324 intrstr
= pci_intr_string(pa
->pa_pc
, ih
);
325 sc
->sc_ih
= pci_intr_establish(pa
->pa_pc
, ih
, IPL_BIO
, ciss_intr
, sc
);
327 aprint_error_dev(&sc
->sc_dev
, "can't establish interrupt");
329 aprint_error(" at %s", intrstr
);
331 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, size
);
332 if (cfg_bar
!= CISS_BAR
)
333 bus_space_unmap(sc
->sc_iot
, sc
->cfg_ioh
, cfgsz
);
336 printf("%s: interrupting at %s\n%s", device_xname(&sc
->sc_dev
), intrstr
,
337 device_xname(&sc
->sc_dev
));
339 if (ciss_attach(sc
)) {
340 pci_intr_disestablish(pa
->pa_pc
, sc
->sc_ih
);
342 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, size
);
343 if (cfg_bar
!= CISS_BAR
)
344 bus_space_unmap(sc
->sc_iot
, sc
->cfg_ioh
, cfgsz
);
348 /* enable interrupts now */
349 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, CISS_IMR
,
350 bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, CISS_IMR
) & ~sc
->iem
);