159078Smdodd/*-
259078Smdodd * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net>
359078Smdodd * All rights reserved.
432801Sjulian *
559078Smdodd * Copyright (c) 1997 Simon Shapiro
659078Smdodd * All Rights Reserved
759078Smdodd *
832801Sjulian * Redistribution and use in source and binary forms, with or without
932801Sjulian * modification, are permitted provided that the following conditions
1032801Sjulian * are met:
1132801Sjulian * 1. Redistributions of source code must retain the above copyright
1259078Smdodd *    notice, this list of conditions and the following disclaimer.
1332801Sjulian * 2. Redistributions in binary form must reproduce the above copyright
1432801Sjulian *    notice, this list of conditions and the following disclaimer in the
1532801Sjulian *    documentation and/or other materials provided with the distribution.
1632801Sjulian *
1732801Sjulian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1832801Sjulian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1932801Sjulian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2059078Smdodd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2159078Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2232801Sjulian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2332801Sjulian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2432801Sjulian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2532801Sjulian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2632801Sjulian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2732801Sjulian * SUCH DAMAGE.
2832801Sjulian */
2932801Sjulian
30119418Sobrien#include <sys/cdefs.h>
31119418Sobrien__FBSDID("$FreeBSD$");
32119418Sobrien
3332801Sjulian#include <sys/param.h>
3432801Sjulian#include <sys/systm.h>
3532801Sjulian#include <sys/kernel.h>
3659078Smdodd#include <sys/module.h>
37117126Sscottl#include <sys/lock.h>
38117126Sscottl#include <sys/mutex.h>
3959078Smdodd#include <sys/bus.h>
4032801Sjulian
4139234Sgibbs#include <machine/bus.h>
4259078Smdodd#include <machine/resource.h>
4359078Smdodd#include <sys/rman.h>
4439234Sgibbs
45119277Simp#include <dev/pci/pcireg.h>
46119277Simp#include <dev/pci/pcivar.h>
4759078Smdodd
4839234Sgibbs#include <cam/scsi/scsi_all.h>
4939234Sgibbs
5039234Sgibbs#include <dev/dpt/dpt.h>
5132801Sjulian
5259078Smdodd#define	DPT_VENDOR_ID		0x1044
5359078Smdodd#define	DPT_DEVICE_ID		0xa400
5432801Sjulian
55119690Sjhb#define	DPT_PCI_IOADDR		PCIR_BAR(0)		/* I/O Address */
56119690Sjhb#define	DPT_PCI_MEMADDR		PCIR_BAR(1)		/* Mem I/O Address */
5732801Sjulian
5859078Smdodd#define	ISA_PRIMARY_WD_ADDRESS	0x1f8
5932801Sjulian
6059078Smdoddstatic int	dpt_pci_probe	(device_t);
6159078Smdoddstatic int	dpt_pci_attach	(device_t);
6232801Sjulian
6359078Smdoddstatic int
6459078Smdodddpt_pci_probe (device_t dev)
6559078Smdodd{
6659078Smdodd	if ((pci_get_vendor(dev) == DPT_VENDOR_ID) &&
6759078Smdodd	    (pci_get_device(dev) == DPT_DEVICE_ID)) {
6859078Smdodd		device_set_desc(dev, "DPT Caching SCSI RAID Controller");
69143161Simp		return (BUS_PROBE_DEFAULT);
7059078Smdodd	}
7159078Smdodd	return (ENXIO);
7259078Smdodd}
7332801Sjulian
7459078Smdoddstatic int
7559078Smdodddpt_pci_attach (device_t dev)
7632801Sjulian{
7759078Smdodd	dpt_softc_t *	dpt;
7859078Smdodd	int		error = 0;
7932801Sjulian
80112780Smdodd	dpt = device_get_softc(dev);
81170872Sscottl	dpt->dev = dev;
82241593Sjhb	dpt_alloc(dev);
83112780Smdodd
8459078Smdodd#ifdef DPT_ALLOW_MMIO
85254263Sscottl	dpt->io_rid = DPT_PCI_MEMADDR;
86254263Sscottl	dpt->io_type = SYS_RES_MEMORY;
87254263Sscottl	dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
88254263Sscottl	    &dpt->io_rid, RF_ACTIVE);
8932801Sjulian#endif
90254263Sscottl	if (dpt->io_res == NULL) {
91112780Smdodd		dpt->io_rid = DPT_PCI_IOADDR;
92112780Smdodd		dpt->io_type = SYS_RES_IOPORT;
93127135Snjl		dpt->io_res = bus_alloc_resource_any(dev, dpt->io_type,
94127135Snjl						     &dpt->io_rid, RF_ACTIVE);
9559078Smdodd	}
9632801Sjulian
97112780Smdodd	if (dpt->io_res == NULL) {
9859078Smdodd		device_printf(dev, "can't allocate register resources\n");
9959078Smdodd		error = ENOMEM;
10059078Smdodd		goto bad;
10159078Smdodd	}
102112780Smdodd	dpt->io_offset = 0x10;
10332801Sjulian
104112780Smdodd	dpt->irq_rid = 0;
105127135Snjl	dpt->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &dpt->irq_rid,
106127135Snjl					      RF_ACTIVE | RF_SHAREABLE);
107112780Smdodd	if (dpt->irq_res == NULL) {
10859078Smdodd		device_printf(dev, "No irq?!\n");
10959078Smdodd		error = ENOMEM;
11059078Smdodd		goto bad;
11159078Smdodd	}
11232801Sjulian
11359078Smdodd	/* Ensure busmastering is enabled */
114241593Sjhb	pci_enable_busmaster(dev);
11532801Sjulian
116112780Smdodd	if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
11732801Sjulian#ifdef DPT_DEBUG_WARN
11859078Smdodd		device_printf(dev, "Mapped as an IDE controller.  "
11959078Smdodd				   "Disabling SCSI setup\n");
12032801Sjulian#endif
12159078Smdodd		error = ENXIO;
12259078Smdodd		goto bad;
12339234Sgibbs	}
12432801Sjulian
12539234Sgibbs	/* Allocate a dmatag representing the capabilities of this attachment */
126232854Sscottl	if (bus_dma_tag_create(	/* PCI parent */ bus_get_dma_tag(dev),
12759078Smdodd				/* alignemnt */	1,
12859078Smdodd				/* boundary  */	0,
12959078Smdodd				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
13059078Smdodd				/* highaddr  */	BUS_SPACE_MAXADDR,
13159078Smdodd				/* filter    */	NULL,
13259078Smdodd				/* filterarg */	NULL,
13359078Smdodd				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
134104710Speter				/* nsegments */	~0,
13559078Smdodd				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
13659078Smdodd				/* flags     */	0,
137241593Sjhb				/* lockfunc  */ NULL,
138241593Sjhb				/* lockarg   */ NULL,
13959078Smdodd				&dpt->parent_dmat) != 0) {
14059078Smdodd		error = ENXIO;
14159078Smdodd		goto bad;
14239234Sgibbs	}
14332801Sjulian
14439234Sgibbs	if (dpt_init(dpt) != 0) {
14559078Smdodd		error = ENXIO;
14659078Smdodd		goto bad;
14739234Sgibbs	}
14832801Sjulian
14939234Sgibbs	/* Register with the XPT */
15039234Sgibbs	dpt_attach(dpt);
15159078Smdodd
152241593Sjhb	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
153241593Sjhb	    INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) {
15459078Smdodd		device_printf(dev, "Unable to register interrupt handler\n");
15559078Smdodd		error = ENXIO;
15659078Smdodd		goto bad;
15759078Smdodd	}
15859078Smdodd
15959078Smdodd	return (error);
16059078Smdodd
16159078Smdoddbad:
162112780Smdodd	dpt_release_resources(dev);
16359078Smdodd
164142356Ssam	dpt_free(dpt);
165112780Smdodd
16659078Smdodd	return (error);
16732801Sjulian}
16859078Smdodd
16959078Smdoddstatic device_method_t dpt_pci_methods[] = {
17059078Smdodd	/* Device interface */
17159078Smdodd	DEVMETHOD(device_probe,         dpt_pci_probe),
17259078Smdodd	DEVMETHOD(device_attach,        dpt_pci_attach),
173112780Smdodd	DEVMETHOD(device_detach,        dpt_detach),
17459078Smdodd
17559078Smdodd	{ 0, 0 }
17659078Smdodd};
17759078Smdodd
17859078Smdoddstatic driver_t dpt_pci_driver = {
17959078Smdodd	"dpt",
18059078Smdodd	dpt_pci_methods,
18159078Smdodd	sizeof(dpt_softc_t),
18259078Smdodd};
18359078Smdodd
18459078SmdoddDRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0);
185165102SmjacobMODULE_DEPEND(dpt, pci, 1, 1, 1);
186165102SmjacobMODULE_DEPEND(dpt, cam, 1, 1, 1);
187