1 /* $NetBSD: mfi_pci.c,v 1.10 2009/07/16 18:10:00 dyoung Exp $ */
2 /* $OpenBSD: mfi_pci.c,v 1.11 2006/08/06 04:40:08 brad Exp $ */
4 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/cdefs.h>
20 __KERNEL_RCSID(0, "$NetBSD: mfi_pci.c,v 1.10 2009/07/16 18:10:00 dyoung Exp $");
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/kernel.h>
25 #include <sys/malloc.h>
26 #include <sys/device.h>
28 #include <dev/pci/pcidevs.h>
29 #include <dev/pci/pcivar.h>
33 #include <dev/scsipi/scsipi_all.h>
34 #include <dev/scsipi/scsipi_disk.h>
35 #include <dev/scsipi/scsiconf.h>
37 #include <dev/ic/mfireg.h>
38 #include <dev/ic/mfivar.h>
41 #define MFI_PCI_MEMSIZE 0x2000 /* 8k */
43 struct mfi_pci_softc
{
44 struct mfi_softc psc_sc
;
45 pci_chipset_tag_t psc_pc
;
48 const struct mfi_pci_device
*mfi_pci_find_device(struct pci_attach_args
*);
49 int mfi_pci_match(device_t
, cfdata_t
, void *);
50 void mfi_pci_attach(device_t
, device_t
, void *);
51 int mfi_pci_detach(device_t
, int);
53 CFATTACH_DECL3_NEW(mfi_pci
, sizeof(struct mfi_pci_softc
),
54 mfi_pci_match
, mfi_pci_attach
, mfi_pci_detach
, NULL
, mfi_rescan
,
55 mfi_childdetached
, DVF_DETACH_SHUTDOWN
);
57 struct mfi_pci_subtype
{
60 const char *st_string
;
63 static const struct mfi_pci_subtype mfi_1078_subtypes
[] = {
64 { PCI_VENDOR_SYMBIOS
, 0x1006, "SAS 8888ELP" },
65 { PCI_VENDOR_SYMBIOS
, 0x100a, "SAS 8708ELP" },
66 { PCI_VENDOR_SYMBIOS
, 0x100f, "SAS 8708E" },
67 { PCI_VENDOR_SYMBIOS
, 0x1012, "SAS 8704ELP" },
68 { PCI_VENDOR_SYMBIOS
, 0x1013, "SAS 8708EM2" },
69 { PCI_VENDOR_SYMBIOS
, 0x1016, "SAS 8880EM2" },
70 { PCI_VENDOR_DELL
, 0x1f0a, "Dell PERC 6/e" },
71 { PCI_VENDOR_DELL
, 0x1f0b, "Dell PERC 6/i" },
72 { PCI_VENDOR_DELL
, 0x1f0c, "Dell PERC 6/i integrated" },
73 { PCI_VENDOR_DELL
, 0x1f0d, "Dell CERC 6/i" },
74 { PCI_VENDOR_DELL
, 0x1f11, "Dell CERC 6/i integrated" },
78 static const struct mfi_pci_subtype mfi_perc5_subtypes
[] = {
79 { PCI_VENDOR_DELL
, 0x1f01, "Dell PERC 5/e" },
80 { PCI_VENDOR_DELL
, 0x1f02, "Dell PERC 5/i" },
81 { PCI_VENDOR_DELL
, 0x1f03, "Dell PERC 5/i integrated" },
86 struct mfi_pci_device
{
90 const struct mfi_pci_subtype
*mpd_subtype
;
91 } mfi_pci_devices
[] = {
92 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_SAS
,
93 MFI_IOP_XSCALE
, NULL
},
94 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_MEGARAID_VERDE_ZCR
,
95 MFI_IOP_XSCALE
, NULL
},
96 { PCI_VENDOR_SYMBIOS
, PCI_PRODUCT_SYMBIOS_SAS1078
,
97 MFI_IOP_PPC
, mfi_1078_subtypes
},
98 { PCI_VENDOR_DELL
, PCI_PRODUCT_DELL_PERC_5
,
99 MFI_IOP_XSCALE
, mfi_perc5_subtypes
},
100 { PCI_VENDOR_DELL
, PCI_PRODUCT_DELL_PERC_6
,
101 MFI_IOP_PPC
, mfi_1078_subtypes
},
104 const struct mfi_pci_device
*
105 mfi_pci_find_device(struct pci_attach_args
*pa
)
107 const struct mfi_pci_device
*mpd
;
110 for (i
= 0; i
< __arraycount(mfi_pci_devices
); i
++) {
111 mpd
= &mfi_pci_devices
[i
];
113 if (mpd
->mpd_vendor
== PCI_VENDOR(pa
->pa_id
) &&
114 mpd
->mpd_product
== PCI_PRODUCT(pa
->pa_id
))
122 mfi_pci_match(device_t parent
, cfdata_t match
, void *aux
)
124 return (mfi_pci_find_device(aux
) != NULL
) ? 1 : 0;
128 mfi_pci_detach(device_t self
, int flags
)
130 struct mfi_pci_softc
*psc
= device_private(self
);
131 struct mfi_softc
*sc
= &psc
->psc_sc
;
134 if ((error
= mfi_detach(sc
, flags
)) != 0)
138 pci_intr_disestablish(psc
->psc_pc
, sc
->sc_ih
);
139 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_size
);
144 mfi_pci_attach(device_t parent
, device_t self
, void *aux
)
146 struct mfi_pci_softc
*psc
= device_private(self
);
147 struct mfi_softc
*sc
= &psc
->psc_sc
;
148 struct pci_attach_args
*pa
= aux
;
149 const struct mfi_pci_device
*mpd
;
150 const struct mfi_pci_subtype
*st
;
152 pci_intr_handle_t ih
;
154 const char *subtype
= NULL
;
158 psc
->psc_pc
= pa
->pa_pc
;
160 csr
= pci_mapreg_type(pa
->pa_pc
, pa
->pa_tag
, MFI_BAR
);
161 csr
|= PCI_MAPREG_MEM_TYPE_32BIT
;
162 if (pci_mapreg_map(pa
, MFI_BAR
, csr
, 0,
163 &sc
->sc_iot
, &sc
->sc_ioh
, NULL
, &sc
->sc_size
)) {
164 aprint_error(": can't map controller pci space\n");
168 sc
->sc_dmat
= pa
->pa_dmat
;
170 if (pci_intr_map(pa
, &ih
)) {
171 aprint_error(": can't map interrupt\n");
172 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_size
);
175 intrstr
= pci_intr_string(pa
->pa_pc
, ih
);
176 sc
->sc_ih
= pci_intr_establish(pa
->pa_pc
, ih
, IPL_BIO
, mfi_intr
, sc
);
178 aprint_error(": can't establish interrupt");
180 aprint_error(" at %s", intrstr
);
182 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_size
);
186 mpd
= mfi_pci_find_device(pa
);
188 subsysid
= pci_conf_read(pa
->pa_pc
, pa
->pa_tag
, PCI_SUBSYS_ID_REG
);
189 if (mpd
->mpd_subtype
!= NULL
) {
190 st
= mpd
->mpd_subtype
;
191 while (st
->st_vendor
!= 0) {
192 if (PCI_VENDOR(subsysid
) == st
->st_vendor
&&
193 PCI_PRODUCT(subsysid
) == st
->st_product
) {
194 subtype
= st
->st_string
;
200 aprint_normal(": %s\n", subtype
);
203 aprint_normal("%s: interrupting at %s\n", DEVNAME(sc
), intrstr
);
205 if (mfi_attach(sc
, mpd
->mpd_iop
)) {
206 aprint_error("%s: can't attach", DEVNAME(sc
));
207 pci_intr_disestablish(pa
->pa_pc
, sc
->sc_ih
);
209 bus_space_unmap(sc
->sc_iot
, sc
->sc_ioh
, sc
->sc_size
);