dpt_pci.c revision 119277
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 *
2959078Smdodd *	$FreeBSD: head/sys/dev/dpt/dpt_pci.c 119277 2003-08-22 05:54:52Z imp $
3032801Sjulian */
3132801Sjulian
3232801Sjulian#include <sys/param.h>
3332801Sjulian#include <sys/systm.h>
3432801Sjulian#include <sys/kernel.h>
3559078Smdodd#include <sys/module.h>
36117126Sscottl#include <sys/lock.h>
37117126Sscottl#include <sys/mutex.h>
3859078Smdodd#include <sys/bus.h>
3932801Sjulian
4039234Sgibbs#include <machine/bus_memio.h>
4139234Sgibbs#include <machine/bus_pio.h>
4239234Sgibbs#include <machine/bus.h>
4359078Smdodd#include <machine/resource.h>
4459078Smdodd#include <sys/rman.h>
4539234Sgibbs
46119277Simp#include <dev/pci/pcireg.h>
47119277Simp#include <dev/pci/pcivar.h>
4859078Smdodd
4939234Sgibbs#include <cam/scsi/scsi_all.h>
5039234Sgibbs
5139234Sgibbs#include <dev/dpt/dpt.h>
5232801Sjulian
5359078Smdodd#define	DPT_VENDOR_ID		0x1044
5459078Smdodd#define	DPT_DEVICE_ID		0xa400
5532801Sjulian
5659078Smdodd#define	DPT_PCI_IOADDR		PCIR_MAPS		/* I/O Address */
5759078Smdodd#define	DPT_PCI_MEMADDR		(PCIR_MAPS + 4)		/* Mem I/O Address */
5832801Sjulian
5959078Smdodd#define	ISA_PRIMARY_WD_ADDRESS	0x1f8
6032801Sjulian
6159078Smdoddstatic int	dpt_pci_probe	(device_t);
6259078Smdoddstatic int	dpt_pci_attach	(device_t);
6332801Sjulian
6459078Smdoddstatic int
6559078Smdodddpt_pci_probe (device_t dev)
6659078Smdodd{
6759078Smdodd	if ((pci_get_vendor(dev) == DPT_VENDOR_ID) &&
6859078Smdodd	    (pci_get_device(dev) == DPT_DEVICE_ID)) {
6959078Smdodd		device_set_desc(dev, "DPT Caching SCSI RAID Controller");
7059078Smdodd		return (0);
7159078Smdodd	}
7259078Smdodd	return (ENXIO);
7359078Smdodd}
7432801Sjulian
7559078Smdoddstatic int
7659078Smdodddpt_pci_attach (device_t dev)
7732801Sjulian{
7859078Smdodd	dpt_softc_t *	dpt;
7959078Smdodd	int		s;
8059078Smdodd	int		error = 0;
8132801Sjulian
8259078Smdodd	u_int32_t	command;
8332801Sjulian
84112780Smdodd	dpt = device_get_softc(dev);
85112780Smdodd
8659078Smdodd	command = pci_read_config(dev, PCIR_COMMAND, /*bytes*/1);
8732801Sjulian
8859078Smdodd#ifdef DPT_ALLOW_MMIO
8959078Smdodd	if ((command & PCIM_CMD_MEMEN) != 0) {
90112780Smdodd		dpt->io_rid = DPT_PCI_MEMADDR;
91112780Smdodd		dpt->io_type = SYS_RES_MEMORY;
92112780Smdodd		dpt->io_res = bus_alloc_resource(dev, dpt->io_type,
93112780Smdodd						 &dpt->io_rid,
94112780Smdodd						 0, ~0, 1, RF_ACTIVE);
9559078Smdodd	}
9632801Sjulian#endif
97112780Smdodd	if (dpt->io_res == NULL && (command &  PCIM_CMD_PORTEN) != 0) {
98112780Smdodd		dpt->io_rid = DPT_PCI_IOADDR;
99112780Smdodd		dpt->io_type = SYS_RES_IOPORT;
100112780Smdodd		dpt->io_res = bus_alloc_resource(dev, dpt->io_type,
101112780Smdodd						 &dpt->io_rid,
102112780Smdodd						 0, ~0, 1, RF_ACTIVE);
10359078Smdodd	}
10432801Sjulian
105112780Smdodd	if (dpt->io_res == NULL) {
10659078Smdodd		device_printf(dev, "can't allocate register resources\n");
10759078Smdodd		error = ENOMEM;
10859078Smdodd		goto bad;
10959078Smdodd	}
110112780Smdodd	dpt->io_offset = 0x10;
11132801Sjulian
112112780Smdodd	dpt->irq_rid = 0;
113112780Smdodd	dpt->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &dpt->irq_rid,
114112780Smdodd					  0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
115112780Smdodd	if (dpt->irq_res == NULL) {
11659078Smdodd		device_printf(dev, "No irq?!\n");
11759078Smdodd		error = ENOMEM;
11859078Smdodd		goto bad;
11959078Smdodd	}
12032801Sjulian
12159078Smdodd	/* Ensure busmastering is enabled */
12259078Smdodd	command |= PCIM_CMD_BUSMASTEREN;
12359078Smdodd	pci_write_config(dev, PCIR_COMMAND, command, /*bytes*/1);
12432801Sjulian
125112780Smdodd	if (rman_get_start(dpt->io_res) == (ISA_PRIMARY_WD_ADDRESS - 0x10)) {
12632801Sjulian#ifdef DPT_DEBUG_WARN
12759078Smdodd		device_printf(dev, "Mapped as an IDE controller.  "
12859078Smdodd				   "Disabling SCSI setup\n");
12932801Sjulian#endif
13059078Smdodd		error = ENXIO;
13159078Smdodd		goto bad;
13239234Sgibbs	}
13332801Sjulian
134112780Smdodd	dpt_alloc(dev);
13532801Sjulian
13639234Sgibbs	/* Allocate a dmatag representing the capabilities of this attachment */
13739234Sgibbs	/* XXX Should be a child of the PCI bus dma tag */
13859078Smdodd	if (bus_dma_tag_create(	/* parent    */	NULL,
13959078Smdodd				/* alignemnt */	1,
14059078Smdodd				/* boundary  */	0,
14159078Smdodd				/* lowaddr   */	BUS_SPACE_MAXADDR_32BIT,
14259078Smdodd				/* highaddr  */	BUS_SPACE_MAXADDR,
14359078Smdodd				/* filter    */	NULL,
14459078Smdodd				/* filterarg */	NULL,
14559078Smdodd				/* maxsize   */	BUS_SPACE_MAXSIZE_32BIT,
146104710Speter				/* nsegments */	~0,
14759078Smdodd				/* maxsegsz  */	BUS_SPACE_MAXSIZE_32BIT,
14859078Smdodd				/* flags     */	0,
149117126Sscottl				/* lockfunc  */ busdma_lock_mutex,
150117126Sscottl				/* lockarg   */ &Giant,
15159078Smdodd				&dpt->parent_dmat) != 0) {
15239234Sgibbs		dpt_free(dpt);
15359078Smdodd		error = ENXIO;
15459078Smdodd		goto bad;
15539234Sgibbs	}
15632801Sjulian
15759078Smdodd	s = splcam();
15832801Sjulian
15939234Sgibbs	if (dpt_init(dpt) != 0) {
16039234Sgibbs		dpt_free(dpt);
16159078Smdodd		error = ENXIO;
16259078Smdodd		goto bad;
16339234Sgibbs	}
16432801Sjulian
16539234Sgibbs	/* Register with the XPT */
16639234Sgibbs	dpt_attach(dpt);
16759078Smdodd
16839234Sgibbs	splx(s);
16959078Smdodd
170112780Smdodd	if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY,
171112780Smdodd			   dpt_intr, dpt, &dpt->ih)) {
17259078Smdodd		device_printf(dev, "Unable to register interrupt handler\n");
17359078Smdodd		error = ENXIO;
17459078Smdodd		goto bad;
17559078Smdodd	}
17659078Smdodd
17759078Smdodd	return (error);
17859078Smdodd
17959078Smdoddbad:
180112780Smdodd	dpt_release_resources(dev);
18159078Smdodd
182112780Smdodd	if (dpt)
183112780Smdodd		dpt_free(dpt);
184112780Smdodd
18559078Smdodd	return (error);
18632801Sjulian}
18759078Smdodd
18859078Smdoddstatic device_method_t dpt_pci_methods[] = {
18959078Smdodd	/* Device interface */
19059078Smdodd	DEVMETHOD(device_probe,         dpt_pci_probe),
19159078Smdodd	DEVMETHOD(device_attach,        dpt_pci_attach),
192112780Smdodd	DEVMETHOD(device_detach,        dpt_detach),
19359078Smdodd
19459078Smdodd	{ 0, 0 }
19559078Smdodd};
19659078Smdodd
19759078Smdoddstatic driver_t dpt_pci_driver = {
19859078Smdodd	"dpt",
19959078Smdodd	dpt_pci_methods,
20059078Smdodd	sizeof(dpt_softc_t),
20159078Smdodd};
20259078Smdodd
20359078SmdoddDRIVER_MODULE(dpt, pci, dpt_pci_driver, dpt_devclass, 0, 0);
204