mlx_pci.c revision 60074
151973Smsmith/*-
251973Smsmith * Copyright (c) 1999 Michael Smith
351973Smsmith * All rights reserved.
451973Smsmith *
551973Smsmith * Redistribution and use in source and binary forms, with or without
651973Smsmith * modification, are permitted provided that the following conditions
751973Smsmith * are met:
851973Smsmith * 1. Redistributions of source code must retain the above copyright
951973Smsmith *    notice, this list of conditions and the following disclaimer.
1051973Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1151973Smsmith *    notice, this list of conditions and the following disclaimer in the
1251973Smsmith *    documentation and/or other materials provided with the distribution.
1351973Smsmith *
1451973Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1551973Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1651973Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1751973Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1851973Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1951973Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2051973Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2151973Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2251973Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2351973Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2451973Smsmith * SUCH DAMAGE.
2551973Smsmith *
2651973Smsmith *	$FreeBSD: head/sys/dev/mlx/mlx_pci.c 60074 2000-05-06 08:54:33Z msmith $
2751973Smsmith */
2851973Smsmith
2951973Smsmith#include <sys/param.h>
3051973Smsmith#include <sys/systm.h>
3151973Smsmith#include <sys/kernel.h>
3251973Smsmith
3351973Smsmith#include <sys/bus.h>
3460041Sphk#include <sys/bio.h>
3551973Smsmith#include <sys/conf.h>
3651973Smsmith#include <sys/devicestat.h>
3751973Smsmith#include <sys/disk.h>
3851973Smsmith
3951973Smsmith#include <machine/bus_memio.h>
4051973Smsmith#include <machine/bus_pio.h>
4151973Smsmith#include <machine/bus.h>
4251973Smsmith#include <machine/resource.h>
4351973Smsmith#include <sys/rman.h>
4451973Smsmith
4551973Smsmith#include <pci/pcireg.h>
4651973Smsmith#include <pci/pcivar.h>
4751973Smsmith
4851973Smsmith#include <dev/mlx/mlxio.h>
4951973Smsmith#include <dev/mlx/mlxvar.h>
5052544Smsmith#include <dev/mlx/mlxreg.h>
5151973Smsmith
5251973Smsmithstatic int			mlx_pci_probe(device_t dev);
5351973Smsmithstatic int			mlx_pci_attach(device_t dev);
5451973Smsmith
5551973Smsmithstatic device_method_t mlx_methods[] = {
5651973Smsmith    /* Device interface */
5751973Smsmith    DEVMETHOD(device_probe,	mlx_pci_probe),
5851973Smsmith    DEVMETHOD(device_attach,	mlx_pci_attach),
5951973Smsmith    DEVMETHOD(device_detach,	mlx_detach),
6051973Smsmith    DEVMETHOD(device_shutdown,	mlx_shutdown),
6151973Smsmith    DEVMETHOD(device_suspend,	mlx_suspend),
6251973Smsmith    DEVMETHOD(device_resume,	mlx_resume),
6351973Smsmith
6451973Smsmith    DEVMETHOD(bus_print_child,	bus_generic_print_child),
6551973Smsmith    DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
6651973Smsmith    { 0, 0 }
6751973Smsmith};
6851973Smsmith
6951973Smsmithstatic driver_t mlx_pci_driver = {
7051973Smsmith	"mlx",
7151973Smsmith	mlx_methods,
7251973Smsmith	sizeof(struct mlx_softc)
7351973Smsmith};
7451973Smsmith
7551973SmsmithDRIVER_MODULE(mlx, pci, mlx_pci_driver, mlx_devclass, 0, 0);
7651973Smsmith
7754419Smsmithstruct mlx_ident
7851973Smsmith{
7951973Smsmith    u_int16_t	vendor;
8051973Smsmith    u_int16_t	device;
8154419Smsmith    u_int16_t	subvendor;
8254419Smsmith    u_int16_t	subdevice;
8351973Smsmith    int		iftype;
8451973Smsmith    char	*desc;
8551973Smsmith} mlx_identifiers[] = {
8658188Smsmith    {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2, "Mylex version 2 RAID interface"},
8754419Smsmith    {0x1069, 0x0002, 0x0000, 0x0000, MLX_IFTYPE_3, "Mylex version 3 RAID interface"},
8854419Smsmith    {0x1069, 0x0010, 0x0000, 0x0000, MLX_IFTYPE_4, "Mylex version 4 RAID interface"},
8954419Smsmith    {0x1011, 0x1065, 0x1069, 0x0020, MLX_IFTYPE_5, "Mylex version 5 RAID interface"},
9054419Smsmith    {0, 0, 0, 0, 0, 0}
9151973Smsmith};
9251973Smsmith
9351973Smsmithstatic int
9451973Smsmithmlx_pci_probe(device_t dev)
9551973Smsmith{
9654419Smsmith    struct mlx_ident	*m;
9751973Smsmith
9858188Smsmith    debug_called(1);
9951973Smsmith
10054419Smsmith    for (m = mlx_identifiers; m->vendor != 0; m++) {
10154419Smsmith	if ((m->vendor == pci_get_vendor(dev)) &&
10254419Smsmith	    (m->device == pci_get_device(dev)) &&
10354419Smsmith	    ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) &&
10454419Smsmith				     (m->subdevice == pci_get_subdevice(dev))))) {
10551973Smsmith
10654419Smsmith	    device_set_desc(dev, m->desc);
10751973Smsmith	    return(0);
10851973Smsmith	}
10951973Smsmith    }
11051973Smsmith    return(ENXIO);
11151973Smsmith}
11251973Smsmith
11351973Smsmithstatic int
11451973Smsmithmlx_pci_attach(device_t dev)
11551973Smsmith{
11651973Smsmith    struct mlx_softc	*sc;
11751973Smsmith    int			i, rid, error;
11851973Smsmith    u_int32_t		command;
11951973Smsmith
12058188Smsmith    debug_called(1);
12151973Smsmith
12251973Smsmith    /*
12351973Smsmith     * Make sure we are going to be able to talk to this board.
12451973Smsmith     */
12558188Smsmith    command = pci_read_config(dev, PCIR_COMMAND, 2);
12651973Smsmith    if ((command & PCIM_CMD_MEMEN) == 0) {
12751973Smsmith	device_printf(dev, "memory window not available\n");
12851973Smsmith	return(ENXIO);
12951973Smsmith    }
13058188Smsmith    /* force the busmaster enable bit on */
13158188Smsmith    command |= PCIM_CMD_BUSMASTEREN;
13258188Smsmith    pci_write_config(dev, PCIR_COMMAND, command, 2);
13351973Smsmith
13451973Smsmith    /*
13551973Smsmith     * Initialise softc.
13651973Smsmith     */
13751973Smsmith    sc = device_get_softc(dev);
13851973Smsmith    bzero(sc, sizeof(*sc));
13951973Smsmith    sc->mlx_dev = dev;
14051973Smsmith
14151973Smsmith    /*
14251973Smsmith     * Work out what sort of adapter this is (we need to know this in order
14351973Smsmith     * to map the appropriate interface resources).
14451973Smsmith     */
14551973Smsmith    sc->mlx_iftype = 0;
14651973Smsmith    for (i = 0; mlx_identifiers[i].vendor != 0; i++) {
14751973Smsmith	if ((mlx_identifiers[i].vendor == pci_get_vendor(dev)) &&
14851973Smsmith	    (mlx_identifiers[i].device == pci_get_device(dev))) {
14951973Smsmith	    sc->mlx_iftype = mlx_identifiers[i].iftype;
15051973Smsmith	    break;
15151973Smsmith	}
15251973Smsmith    }
15351973Smsmith    if (sc->mlx_iftype == 0)		/* shouldn't happen */
15451973Smsmith	return(ENXIO);
15551973Smsmith
15651973Smsmith    /*
15751973Smsmith     * Allocate the PCI register window.
15851973Smsmith     */
15951973Smsmith
16058188Smsmith    /* type 2/3 adapters have an I/O region we don't use at base 0 */
16158188Smsmith    switch(sc->mlx_iftype) {
16258188Smsmith    case MLX_IFTYPE_2:
16358188Smsmith    case MLX_IFTYPE_3:
16458188Smsmith	rid = MLX_CFG_BASE1;
16558188Smsmith	break;
16658188Smsmith    case MLX_IFTYPE_4:
16758188Smsmith    case MLX_IFTYPE_5:
16858188Smsmith	rid = MLX_CFG_BASE0;
16958188Smsmith	break;
17058188Smsmith    }
17151973Smsmith    sc->mlx_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE);
17251973Smsmith    if (sc->mlx_mem == NULL) {
17351973Smsmith	device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n");
17451973Smsmith	mlx_free(sc);
17551973Smsmith	return(ENXIO);
17651973Smsmith    }
17751973Smsmith    sc->mlx_btag = rman_get_bustag(sc->mlx_mem);
17851973Smsmith    sc->mlx_bhandle = rman_get_bushandle(sc->mlx_mem);
17951973Smsmith
18051973Smsmith    /*
18151973Smsmith     * Allocate the parent bus DMA tag appropriate for PCI.
18251973Smsmith     */
18351973Smsmith    error = bus_dma_tag_create(NULL, 			/* parent */
18451973Smsmith			       1, 0, 			/* alignment, boundary */
18551973Smsmith			       BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
18651973Smsmith			       BUS_SPACE_MAXADDR, 	/* highaddr */
18751973Smsmith			       NULL, NULL, 		/* filter, filterarg */
18860074Smsmith			       MAXBSIZE, MLX_NSEG,	/* maxsize, nsegments */
18951973Smsmith			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
19051973Smsmith			       BUS_DMA_ALLOCNOW,	/* flags */
19151973Smsmith			       &sc->mlx_parent_dmat);
19251973Smsmith    if (error != 0) {
19351973Smsmith	device_printf(dev, "can't allocate parent DMA tag\n");
19451973Smsmith	mlx_free(sc);
19551973Smsmith	return(ENOMEM);
19651973Smsmith    }
19751973Smsmith
19851973Smsmith    /*
19951973Smsmith     * Do bus-independant initialisation.
20051973Smsmith     */
20151973Smsmith    error = mlx_attach(sc);
20251973Smsmith    if (error != 0) {
20351973Smsmith	mlx_free(sc);
20451973Smsmith	return(error);
20551973Smsmith    }
20651973Smsmith
20751973Smsmith    /*
20851973Smsmith     * Start the controller.
20951973Smsmith     */
21051973Smsmith    mlx_startup(sc);
21151973Smsmith    return(0);
21251973Smsmith}
213