mfi_pci.c revision 1.15
1/* $OpenBSD: mfi_pci.c,v 1.15 2008/02/11 01:07:02 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 <sys/param.h>
19#include <sys/systm.h>
20#include <sys/kernel.h>
21#include <sys/malloc.h>
22#include <sys/device.h>
23#include <sys/rwlock.h>
24
25#include <dev/pci/pcidevs.h>
26#include <dev/pci/pcivar.h>
27
28#include <machine/bus.h>
29
30#include <scsi/scsi_all.h>
31#include <scsi/scsi_disk.h>
32#include <scsi/scsiconf.h>
33
34#include <dev/ic/mfireg.h>
35#include <dev/ic/mfivar.h>
36
37#define	MFI_BAR		0x10
38#define	MFI_PCI_MEMSIZE	0x2000 /* 8k */
39
40int	mfi_pci_match(struct device *, void *, void *);
41void	mfi_pci_attach(struct device *, struct device *, void *);
42
43struct cfattach mfi_pci_ca = {
44	sizeof(struct mfi_softc), mfi_pci_match, mfi_pci_attach
45};
46
47static const
48struct	mfi_pci_device {
49	pcireg_t	mpd_vendor;
50	pcireg_t	mpd_product;
51	enum mfi_iop	mpd_iop;
52} mfi_pci_devices[] = {
53	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_SAS,
54	  MFI_IOP_XSCALE },
55	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_VERDE_ZCR,
56	  MFI_IOP_XSCALE },
57	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS1078,
58	  MFI_IOP_PPC },
59	{ PCI_VENDOR_DELL,	PCI_PRODUCT_DELL_PERC5,
60	  MFI_IOP_XSCALE },
61	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_DELL_PERC6,
62	  MFI_IOP_PPC }
63};
64
65#define sizeofa(_a) (sizeof(_a) / sizeof((_a)[0]))
66const struct mfi_pci_device *mfi_pci_find_device(struct pci_attach_args *);
67
68const struct mfi_pci_device *
69mfi_pci_find_device(struct pci_attach_args *pa)
70{
71	const struct mfi_pci_device *mpd;
72	int i;
73
74	for (i = 0; i < sizeofa(mfi_pci_devices); i++) {
75		mpd = &mfi_pci_devices[i];
76
77		if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
78		    mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
79			return (mpd);
80	}
81
82	return (NULL);
83}
84
85int
86mfi_pci_match(struct device *parent, void *match, void *aux)
87{
88	return ((mfi_pci_find_device(aux) != NULL) ? 1 : 0);
89}
90
91void
92mfi_pci_attach(struct device *parent, struct device *self, void *aux)
93{
94	struct mfi_softc	*sc = (struct mfi_softc *)self;
95	struct pci_attach_args	*pa = aux;
96	const struct mfi_pci_device *mpd;
97	const char		*intrstr;
98	pci_intr_handle_t	ih;
99	bus_size_t		size;
100	pcireg_t		csr;
101
102	mpd = mfi_pci_find_device(pa);
103
104	csr = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MFI_BAR);
105	if (pci_mapreg_map(pa, MFI_BAR, csr, 0,
106	    &sc->sc_iot, &sc->sc_ioh, NULL, &size, MFI_PCI_MEMSIZE)) {
107		printf(": can't map controller pci space\n");
108		return;
109	}
110
111	sc->sc_dmat = pa->pa_dmat;
112
113	if (pci_intr_map(pa, &ih)) {
114		printf(": can't map interrupt\n");
115		bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
116		return;
117	}
118	intrstr = pci_intr_string(pa->pa_pc, ih);
119	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, mfi_intr, sc,
120	    sc->sc_dev.dv_xname);
121	if (!sc->sc_ih) {
122		printf(": can't establish interrupt");
123		if (intrstr)
124			printf(" at %s", intrstr);
125		printf("\n");
126		bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
127		return;
128	}
129
130	printf(": %s\n", intrstr);
131
132	if (mfi_attach(sc, mpd->mpd_iop)) {
133		printf("%s: can't attach\n", DEVNAME(sc));
134		pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
135		sc->sc_ih = NULL;
136		bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
137	}
138}
139