dpt_pci.c revision 254263
1193323Sed/*-
2193323Sed * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * Copyright (c) 1997 Simon Shapiro
6193323Sed * All Rights Reserved
7193323Sed *
8193323Sed * Redistribution and use in source and binary forms, with or without
9193323Sed * modification, are permitted provided that the following conditions
10193323Sed * are met:
11193323Sed * 1. Redistributions of source code must retain the above copyright
12195340Sed *    notice, this list of conditions and the following disclaimer.
13193323Sed * 2. Redistributions in binary form must reproduce the above copyright
14193323Sed *    notice, this list of conditions and the following disclaimer in the
15193323Sed *    documentation and/or other materials provided with the distribution.
16243830Sdim *
17249423Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18263508Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19243830Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20212793Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23195098Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24195098Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26195098Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27234353Sdim * SUCH DAMAGE.
28218885Sdim */
29249423Sdim
30263508Sdim#include <sys/cdefs.h>
31249423Sdim__FBSDID("$FreeBSD: head/sys/dev/dpt/dpt_pci.c 254263 2013-08-12 23:30:01Z scottl $");
32249423Sdim
33263508Sdim#include <sys/param.h>
34249423Sdim#include <sys/systm.h>
35193323Sed#include <sys/kernel.h>
36249423Sdim#include <sys/module.h>
37249423Sdim#include <sys/lock.h>
38249423Sdim#include <sys/mutex.h>
39193323Sed#include <sys/bus.h>
40249423Sdim
41249423Sdim#include <machine/bus.h>
42193323Sed#include <machine/resource.h>
43193323Sed#include <sys/rman.h>
44193323Sed
45218885Sdim#include <dev/pci/pcireg.h>
46263508Sdim#include <dev/pci/pcivar.h>
47218885Sdim
48249423Sdim#include <cam/scsi/scsi_all.h>
49226584Sdim
50249423Sdim#include <dev/dpt/dpt.h>
51263508Sdim
52193323Sed#define	DPT_VENDOR_ID		0x1044
53218885Sdim#define	DPT_DEVICE_ID		0xa400
54218885Sdim
55218885Sdim#define	DPT_PCI_IOADDR		PCIR_BAR(0)		/* I/O Address */
56218885Sdim#define	DPT_PCI_MEMADDR		PCIR_BAR(1)		/* Mem I/O Address */
57218885Sdim
58218885Sdim#define	ISA_PRIMARY_WD_ADDRESS	0x1f8
59218885Sdim
60218885Sdimstatic int	dpt_pci_probe	(device_t);
61193323Sedstatic int	dpt_pci_attach	(device_t);
62193323Sed
63193323Sedstatic int
64193323Seddpt_pci_probe (device_t dev)
65193323Sed{
66193323Sed	if ((pci_get_vendor(dev) == DPT_VENDOR_ID) &&
67193323Sed	    (pci_get_device(dev) == DPT_DEVICE_ID)) {
68193323Sed		device_set_desc(dev, "DPT Caching SCSI RAID Controller");
69193323Sed		return (BUS_PROBE_DEFAULT);
70193323Sed	}
71193323Sed	return (ENXIO);
72193323Sed}
73193323Sed
74218885Sdimstatic int
75218885Sdimdpt_pci_attach (device_t dev)
76218885Sdim{
77218885Sdim	dpt_softc_t *	dpt;
78263508Sdim	int		error = 0;
79263508Sdim
80263508Sdim	dpt = device_get_softc(dev);
81263508Sdim	dpt->dev = dev;
82243830Sdim	dpt_alloc(dev);
83243830Sdim
84243830Sdim#ifdef DPT_ALLOW_MMIO
85243830Sdim	dpt->io_rid = DPT_PCI_MEMADDR;
86243830Sdim	dpt->io_type = SYS_RES_MEMORY;
87243830Sdim	dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
88243830Sdim	    &dpt->io_rid, RF_ACTIVE);
89263508Sdim#endif
90263508Sdim	if (dpt->io_res == NULL) {
91263508Sdim		dpt->io_rid = DPT_PCI_IOADDR;
92263508Sdim		dpt->io_type = SYS_RES_IOPORT;
93263508Sdim		dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
94263508Sdim						     &dpt->io_rid, RF_ACTIVE);
95263508Sdim	}
96263508Sdim
97263508Sdim	if (dpt->io_res == NULL) {
98263508Sdim		device_printf(dev, "can't allocate register resources\n");
99263508Sdim		error = ENOMEM;
100263508Sdim		goto bad;
101193323Sed	}
102193323Sed	dpt->io_offset = 0x10;
103193323Sed
104193323Sed	dpt->irq_rid = 0;
105193323Sed	dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid,
106193323Sed					      RF_ACTIVE | RF_SHAREABLE);
107193323Sed	if (dpt->irq_res == NULL) {
108193323Sed		device_printf(dev, "No irq?!\n");
109193323Sed		error = ENOMEM;
110193323Sed		goto bad;
111193323Sed	}
112193323Sed
113193323Sed	/* Ensure busmastering is enabled */
114203954Srdivacky	pci_enable_busmaster(dev);
115203954Srdivacky
116203954Srdivacky	if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
117203954Srdivacky#ifdef DPT_DEBUG_WARN
118203954Srdivacky		device_printf(dev, "Mapped as an IDE controller.  "
119203954Srdivacky				   "Disabling SCSI setup\n");
120203954Srdivacky#endif
121203954Srdivacky		error = ENXIO;
122203954Srdivacky		goto bad;
123203954Srdivacky	}
124203954Srdivacky
125203954Srdivacky	/* Allocate a dmatag representing the capabilities of this attachment */
126203954Srdivacky	if (bus_dma_tag_create(	/* PCI parent */ bus_get_dma_tag(dev),
127203954Srdivacky				/* alignemnt */	1,
128203954Srdivacky				/* boundary  */	0,
129203954Srdivacky				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
130193323Sed				/* highaddr  */	BUS_SPACE_MAXADDR,
131193323Sed				/* filter    */	NULL,
132193323Sed				/* filterarg */	NULL,
133193323Sed				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
134193323Sed				/* nsegments */	~0,
135234353Sdim				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
136263508Sdim				/* flags     */	0,
137263508Sdim				/* lockfunc  */ NULL,
138263508Sdim				/* lockarg   */ NULL,
139263508Sdim				&dpt->parent_dmat) != 0) {
140263508Sdim		error = ENXIO;
141193323Sed		goto bad;
142193323Sed	}
143193323Sed
144193323Sed	if (dpt_init(dpt) != 0) {
145234353Sdim		error = ENXIO;
146193323Sed		goto bad;
147193323Sed	}
148193323Sed
149193323Sed	/* Register with the XPT */
150193323Sed	dpt_attach(dpt);
151193323Sed
152193323Sed	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
153193323Sed	    INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) {
154226584Sdim		device_printf(dev, "Unable to register interrupt handler\n");
155226584Sdim		error = ENXIO;
156226584Sdim		goto bad;
157226584Sdim	}
158226584Sdim
159226584Sdim	return (error);
160226584Sdim
161226584Sdimbad:
162226584Sdim	dpt_release_resources(dev);
163226584Sdim
164226584Sdim	dpt_free(dpt);
165226584Sdim
166226584Sdim	return (error);
167226584Sdim}
168226584Sdim
169226584Sdimstatic device_method_t dpt_pci_methods[] = {
170226584Sdim	/* Device interface */
171226584Sdim	DEVMETHOD(device_probe,         dpt_pci_probe),
172226584Sdim	DEVMETHOD(device_attach,        dpt_pci_attach),
173226584Sdim	DEVMETHOD(device_detach,        dpt_detach),
174226584Sdim
175226584Sdim	{ 0, 0 }
176226584Sdim};
177226584Sdim
178226584Sdimstatic driver_t dpt_pci_driver = {
179226584Sdim	"dpt",
180226584Sdim	dpt_pci_methods,
181226584Sdim	sizeof(dpt_softc_t),
182226584Sdim};
183226584Sdim
184226584SdimDRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0);
185226584SdimMODULE_DEPEND(dpt, pci, 1, 1, 1);
186234982SdimMODULE_DEPEND(dpt, cam, 1, 1, 1);
187243830Sdim