Line data Source code
1 : /* $OpenBSD: mfi_pci.c,v 1.29 2014/09/09 03:08:30 dlg Exp $ */
2 : /*
3 : * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
4 : *
5 : * Permission to use, copy, modify, and distribute this software for any
6 : * purpose with or without fee is hereby granted, provided that the above
7 : * copyright notice and this permission notice appear in all copies.
8 : *
9 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 : */
17 :
18 : #include "bio.h"
19 :
20 : #include <sys/param.h>
21 : #include <sys/systm.h>
22 : #include <sys/kernel.h>
23 : #include <sys/malloc.h>
24 : #include <sys/device.h>
25 : #include <sys/rwlock.h>
26 :
27 : #include <dev/pci/pcidevs.h>
28 : #include <dev/pci/pcivar.h>
29 :
30 : #include <machine/bus.h>
31 :
32 : #include <scsi/scsi_all.h>
33 : #include <scsi/scsi_disk.h>
34 : #include <scsi/scsiconf.h>
35 :
36 : #include <dev/ic/mfireg.h>
37 : #include <dev/ic/mfivar.h>
38 :
39 : #define MFI_BAR 0x10
40 : #define MFI_BAR_GEN2 0x14
41 : #define MFI_PCI_MEMSIZE 0x2000 /* 8k */
42 :
43 : int mfi_pci_match(struct device *, void *, void *);
44 : void mfi_pci_attach(struct device *, struct device *, void *);
45 :
46 : struct cfattach mfi_pci_ca = {
47 : sizeof(struct mfi_softc), mfi_pci_match, mfi_pci_attach
48 : };
49 :
50 : static const
51 : struct mfi_pci_device {
52 : pcireg_t mpd_vendor;
53 : pcireg_t mpd_product;
54 : enum mfi_iop mpd_iop;
55 : } mfi_pci_devices[] = {
56 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_SAS,
57 : MFI_IOP_XSCALE },
58 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_MEGARAID_VERDE_ZCR,
59 : MFI_IOP_XSCALE },
60 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078,
61 : MFI_IOP_PPC },
62 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS1078DE,
63 : MFI_IOP_PPC },
64 : { PCI_VENDOR_DELL, PCI_PRODUCT_DELL_PERC5,
65 : MFI_IOP_XSCALE },
66 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_1,
67 : MFI_IOP_GEN2 },
68 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_2,
69 : MFI_IOP_GEN2 },
70 : { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2008_1,
71 : MFI_IOP_SKINNY }
72 : };
73 :
74 : const struct mfi_pci_device *mfi_pci_find_device(struct pci_attach_args *);
75 :
76 : const struct mfi_pci_device *
77 0 : mfi_pci_find_device(struct pci_attach_args *pa)
78 : {
79 : const struct mfi_pci_device *mpd;
80 : int i;
81 :
82 0 : for (i = 0; i < nitems(mfi_pci_devices); i++) {
83 0 : mpd = &mfi_pci_devices[i];
84 :
85 0 : if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
86 0 : mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
87 0 : return (mpd);
88 : }
89 :
90 0 : return (NULL);
91 0 : }
92 :
93 : int
94 0 : mfi_pci_match(struct device *parent, void *match, void *aux)
95 : {
96 0 : return ((mfi_pci_find_device(aux) != NULL) ? 1 : 0);
97 : }
98 :
99 : void
100 0 : mfi_pci_attach(struct device *parent, struct device *self, void *aux)
101 : {
102 0 : struct mfi_softc *sc = (struct mfi_softc *)self;
103 0 : struct pci_attach_args *pa = aux;
104 : const struct mfi_pci_device *mpd;
105 0 : pci_intr_handle_t ih;
106 0 : bus_size_t size;
107 : pcireg_t reg;
108 : int regbar;
109 :
110 0 : mpd = mfi_pci_find_device(pa);
111 0 : if (mpd == NULL) {
112 0 : printf(": can't find matching pci device\n");
113 0 : return;
114 : }
115 :
116 0 : if (mpd->mpd_iop == MFI_IOP_GEN2 || mpd->mpd_iop == MFI_IOP_SKINNY)
117 0 : regbar = MFI_BAR_GEN2;
118 : else
119 : regbar = MFI_BAR;
120 :
121 0 : reg = pci_mapreg_type(pa->pa_pc, pa->pa_tag, regbar);
122 0 : if (pci_mapreg_map(pa, regbar, reg, 0,
123 0 : &sc->sc_iot, &sc->sc_ioh, NULL, &size, MFI_PCI_MEMSIZE)) {
124 0 : printf(": can't map controller pci space\n");
125 0 : return;
126 : }
127 :
128 0 : sc->sc_dmat = pa->pa_dmat;
129 :
130 0 : if (pci_intr_map(pa, &ih) != 0) {
131 0 : printf(": can't map interrupt\n");
132 0 : goto unmap;
133 : }
134 0 : printf(": %s\n", pci_intr_string(pa->pa_pc, ih));
135 :
136 0 : sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO | IPL_MPSAFE,
137 0 : mfi_intr, sc, sc->sc_dev.dv_xname);
138 0 : if (!sc->sc_ih) {
139 0 : printf("%s: can't establish interrupt\n", DEVNAME(sc));
140 0 : goto unmap;
141 : }
142 :
143 0 : if (mfi_attach(sc, mpd->mpd_iop)) {
144 0 : printf("%s: can't attach\n", DEVNAME(sc));
145 : goto unintr;
146 : }
147 :
148 0 : return;
149 : unintr:
150 0 : pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
151 0 : sc->sc_ih = NULL;
152 : unmap:
153 0 : bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
154 0 : }
|