dpt_pci.c revision 119418
1238384Sjkim/*-
2238384Sjkim * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
3238384Sjkim * All rights reserved.
4238384Sjkim *
5238384Sjkim * Copyright (c) 1997 Simon Shapiro
6238384Sjkim * All Rights Reserved
7238384Sjkim *
8238384Sjkim * Redistribution and use in source and binary forms, with or without
9238384Sjkim * modification, are permitted provided that the following conditions
10273144Sjkim * are met:
11273144Sjkim * 1. Redistributions of source code must retain the above copyright
12273144Sjkim *    notice, this list of conditions and the following disclaimer.
13280297Sjkim * 2. Redistributions in binary form must reproduce the above copyright
14280297Sjkim *    notice, this list of conditions and the following disclaimer in the
15238384Sjkim *    documentation and/or other materials provided with the distribution.
16280297Sjkim *
17280297Sjkim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18280297Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20280297Sjkim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21280297Sjkim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22280297Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23238384Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24280297Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25280297Sjkim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26280297Sjkim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27280297Sjkim * SUCH DAMAGE.
28238384Sjkim */
29238384Sjkim
30280297Sjkim#include <sys/cdefs.h>
31280297Sjkim__FBSDID("$FreeBSD: head/sys/dev/dpt/dpt_pci.c 119418 2003-08-24 17:55:58Z obrien $");
32238384Sjkim
33280297Sjkim#include <sys/param.h>
34280297Sjkim#include <sys/systm.h>
35238384Sjkim#include <sys/kernel.h>
36238384Sjkim#include <sys/module.h>
37280297Sjkim#include <sys/lock.h>
38280297Sjkim#include <sys/mutex.h>
39280297Sjkim#include <sys/bus.h>
40280297Sjkim
41238384Sjkim#include <machine/bus_memio.h>
42238384Sjkim#include <machine/bus_pio.h>
43280297Sjkim#include <machine/bus.h>
44280297Sjkim#include <machine/resource.h>
45280297Sjkim#include <sys/rman.h>
46280297Sjkim
47238384Sjkim#include <dev/pci/pcireg.h>
48238384Sjkim#include <dev/pci/pcivar.h>
49280297Sjkim
50280297Sjkim#include <cam/scsi/scsi_all.h>
51280297Sjkim
52238384Sjkim#include <dev/dpt/dpt.h>
53238384Sjkim
54280297Sjkim#define	DPT_VENDOR_ID		0x1044
55280297Sjkim#define	DPT_DEVICE_ID		0xa400
56280297Sjkim
57238384Sjkim#define	DPT_PCI_IOADDR		PCIR_MAPS		/* I/O Address */
58280297Sjkim#define	DPT_PCI_MEMADDR		(PCIR_MAPS + 4)		/* Mem I/O Address */
59280297Sjkim
60280297Sjkim#define	ISA_PRIMARY_WD_ADDRESS	0x1f8
61238384Sjkim
62280297Sjkimstatic int	dpt_pci_probe	(device_t);
63280297Sjkimstatic int	dpt_pci_attach	(device_t);
64280297Sjkim
65238384Sjkimstatic int
66280297Sjkimdpt_pci_probe (device_t dev)
67280297Sjkim{
68280297Sjkim	if ((pci_get_vendor(dev) == DPT_VENDOR_ID) &&
69280297Sjkim	    (pci_get_device(dev) == DPT_DEVICE_ID)) {
70238384Sjkim		device_set_desc(dev, "DPT Caching SCSI RAID Controller");
71280297Sjkim		return (0);
72280297Sjkim	}
73280297Sjkim	return (ENXIO);
74280297Sjkim}
75280297Sjkim
76280297Sjkimstatic int
77238384Sjkimdpt_pci_attach (device_t dev)
78280297Sjkim{
79280297Sjkim	dpt_softc_t *	dpt;
80238384Sjkim	int		s;
81280297Sjkim	int		error = 0;
82280297Sjkim
83280297Sjkim	u_int32_t	command;
84280297Sjkim
85280297Sjkim	dpt = device_get_softc(dev);
86238384Sjkim
87280297Sjkim	command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
88280297Sjkim
89280297Sjkim#ifdef DPT_ALLOW_MMIO
90280297Sjkim	if ((command & PCIM_CMD_MEMEN) != 0) {
91280297Sjkim		dpt->io_rid = DPT_PCI_MEMADDR;
92280297Sjkim		dpt->io_type = SYS_RES_MEMORY;
93280297Sjkim		dpt->io_res = bus_alloc_resource(dev, dpt->io_type,
94238384Sjkim						 &dpt->io_rid,
95280297Sjkim						 0, ~0, 1, RF_ACTIVE);
96280297Sjkim	}
97238384Sjkim#endif
98238384Sjkim	if (dpt->io_res == NULL && (command &  PCIM_CMD_PORTEN) != 0) {
99238384Sjkim		dpt->io_rid = DPT_PCI_IOADDR;
100238384Sjkim		dpt->io_type = SYS_RES_IOPORT;
101280297Sjkim		dpt->io_res = bus_alloc_resource(dev, dpt->io_type,
102238384Sjkim						 &dpt->io_rid,
103280297Sjkim						 0, ~0, 1, RF_ACTIVE);
104238384Sjkim	}
105280297Sjkim
106238384Sjkim	if (dpt->io_res == NULL) {
107280297Sjkim		device_printf(dev, "can't allocate register resources\n");
108280297Sjkim		error = ENOMEM;
109238384Sjkim		goto bad;
110280297Sjkim	}
111280297Sjkim	dpt->io_offset = 0x10;
112238384Sjkim
113280297Sjkim	dpt->irq_rid = 0;
114280297Sjkim	dpt->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &dpt->irq_rid,
115238384Sjkim					  0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
116280297Sjkim	if (dpt->irq_res == NULL) {
117280297Sjkim		device_printf(dev, "No irq?!\n");
118280297Sjkim		error = ENOMEM;
119280297Sjkim		goto bad;
120238384Sjkim	}
121238384Sjkim
122238384Sjkim	/* Ensure busmastering is enabled */
123238384Sjkim	command |= PCIM_CMD_BUSMASTEREN;
124238384Sjkim	pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
125238384Sjkim
126280297Sjkim	if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
127280297Sjkim#ifdef DPT_DEBUG_WARN
128280297Sjkim		device_printf(dev, "Mapped as an IDE controller.  "
129280297Sjkim				   "Disabling SCSI setup\n");
130280297Sjkim#endif
131280297Sjkim		error = ENXIO;
132280297Sjkim		goto bad;
133280297Sjkim	}
134280297Sjkim
135280297Sjkim	dpt_alloc(dev);
136280297Sjkim
137280297Sjkim	/* Allocate a dmatag representing the capabilities of this attachment */
138280297Sjkim	/* XXX Should be a child of the PCI bus dma tag */
139280297Sjkim	if (bus_dma_tag_create(	/* parent    */	NULL,
140280297Sjkim				/* alignemnt */	1,
141280297Sjkim				/* boundary  */	0,
142238384Sjkim				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
143238384Sjkim				/* highaddr  */	BUS_SPACE_MAXADDR,
144238384Sjkim				/* filter    */	NULL,
145238384Sjkim				/* filterarg */	NULL,
146280297Sjkim				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
147280297Sjkim				/* nsegments */	~0,
148280297Sjkim				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
149280297Sjkim				/* flags     */	0,
150280297Sjkim				/* lockfunc  */ busdma_lock_mutex,
151290207Sjkim				/* lockarg   */ &Giant,
152290207Sjkim				&dpt->parent_dmat) != 0) {
153290207Sjkim		dpt_free(dpt);
154290207Sjkim		error = ENXIO;
155290207Sjkim		goto bad;
156290207Sjkim	}
157290207Sjkim
158290207Sjkim	s = splcam();
159290207Sjkim
160290207Sjkim	if (dpt_init(dpt) != 0) {
161273144Sjkim		dpt_free(dpt);
162273144Sjkim		error = ENXIO;
163273144Sjkim		goto bad;
164	}
165
166	/* Register with the XPT */
167	dpt_attach(dpt);
168
169	splx(s);
170
171	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY,
172			   dpt_intr, dpt, &dpt->ih)) {
173		device_printf(dev, "Unable to register interrupt handler\n");
174		error = ENXIO;
175		goto bad;
176	}
177
178	return (error);
179
180bad:
181	dpt_release_resources(dev);
182
183	if (dpt)
184		dpt_free(dpt);
185
186	return (error);
187}
188
189static device_method_t dpt_pci_methods[] = {
190	/* Device interface */
191	DEVMETHOD(device_probe,         dpt_pci_probe),
192	DEVMETHOD(device_attach,        dpt_pci_attach),
193	DEVMETHOD(device_detach,        dpt_detach),
194
195	{ 0, 0 }
196};
197
198static driver_t dpt_pci_driver = {
199	"dpt",
200	dpt_pci_methods,
201	sizeof(dpt_softc_t),
202};
203
204DRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0);
205