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
27119418Sobrien#include <sys/cdefs.h>
28119418Sobrien__FBSDID("$FreeBSD$");
29119418Sobrien
3051973Smsmith#include <sys/param.h>
3151973Smsmith#include <sys/systm.h>
32240963Sjhb#include <sys/bio.h>
3351973Smsmith#include <sys/kernel.h>
34240608Sjhb#include <sys/lock.h>
35129879Sphk#include <sys/module.h>
36240608Sjhb#include <sys/mutex.h>
37240608Sjhb#include <sys/sx.h>
3851973Smsmith
3951973Smsmith#include <sys/bus.h>
4051973Smsmith#include <sys/conf.h>
4151973Smsmith
4251973Smsmith#include <machine/bus.h>
4351973Smsmith#include <machine/resource.h>
4451973Smsmith#include <sys/rman.h>
4551973Smsmith
46112946Sphk#include <geom/geom_disk.h>
47112946Sphk
48119285Simp#include <dev/pci/pcireg.h>
49119285Simp#include <dev/pci/pcivar.h>
5051973Smsmith
5151973Smsmith#include <dev/mlx/mlxio.h>
5251973Smsmith#include <dev/mlx/mlxvar.h>
5352544Smsmith#include <dev/mlx/mlxreg.h>
5451973Smsmith
5551973Smsmithstatic int			mlx_pci_probe(device_t dev);
5651973Smsmithstatic int			mlx_pci_attach(device_t dev);
5751973Smsmith
5851973Smsmithstatic device_method_t mlx_methods[] = {
5951973Smsmith    /* Device interface */
6051973Smsmith    DEVMETHOD(device_probe,	mlx_pci_probe),
6151973Smsmith    DEVMETHOD(device_attach,	mlx_pci_attach),
6251973Smsmith    DEVMETHOD(device_detach,	mlx_detach),
6351973Smsmith    DEVMETHOD(device_shutdown,	mlx_shutdown),
6451973Smsmith    DEVMETHOD(device_suspend,	mlx_suspend),
6551973Smsmith    DEVMETHOD(device_resume,	mlx_resume),
6651973Smsmith
67227843Smarius    DEVMETHOD_END
6851973Smsmith};
6951973Smsmith
7051973Smsmithstatic driver_t mlx_pci_driver = {
7151973Smsmith	"mlx",
7251973Smsmith	mlx_methods,
7351973Smsmith	sizeof(struct mlx_softc)
7451973Smsmith};
7551973Smsmith
7651973SmsmithDRIVER_MODULE(mlx, pci, mlx_pci_driver, mlx_devclass, 0, 0);
7751973Smsmith
7854419Smsmithstruct mlx_ident
7951973Smsmith{
8051973Smsmith    u_int16_t	vendor;
8151973Smsmith    u_int16_t	device;
8254419Smsmith    u_int16_t	subvendor;
8354419Smsmith    u_int16_t	subdevice;
8451973Smsmith    int		iftype;
8551973Smsmith    char	*desc;
8651973Smsmith} mlx_identifiers[] = {
8758188Smsmith    {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2, "Mylex version 2 RAID interface"},
8854419Smsmith    {0x1069, 0x0002, 0x0000, 0x0000, MLX_IFTYPE_3, "Mylex version 3 RAID interface"},
8954419Smsmith    {0x1069, 0x0010, 0x0000, 0x0000, MLX_IFTYPE_4, "Mylex version 4 RAID interface"},
9054419Smsmith    {0x1011, 0x1065, 0x1069, 0x0020, MLX_IFTYPE_5, "Mylex version 5 RAID interface"},
9154419Smsmith    {0, 0, 0, 0, 0, 0}
9251973Smsmith};
9351973Smsmith
94240608Sjhbstatic struct mlx_ident *
95240608Sjhbmlx_pci_match(device_t dev)
96240608Sjhb{
97240608Sjhb    struct mlx_ident *m;
98240608Sjhb
99240608Sjhb    for (m = mlx_identifiers; m->vendor != 0; m++) {
100240608Sjhb	if ((m->vendor == pci_get_vendor(dev)) &&
101240608Sjhb	    (m->device == pci_get_device(dev)) &&
102240608Sjhb	    ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) &&
103240608Sjhb				     (m->subdevice == pci_get_subdevice(dev)))))
104240608Sjhb	    return (m);
105240608Sjhb    }
106240608Sjhb    return (NULL);
107240608Sjhb}
108240608Sjhb
10951973Smsmithstatic int
11051973Smsmithmlx_pci_probe(device_t dev)
11151973Smsmith{
11254419Smsmith    struct mlx_ident	*m;
11351973Smsmith
11458188Smsmith    debug_called(1);
11551973Smsmith
116240608Sjhb    m = mlx_pci_match(dev);
117240608Sjhb    if (m != NULL) {
118240608Sjhb	device_set_desc(dev, m->desc);
119240608Sjhb	return(BUS_PROBE_DEFAULT);
12051973Smsmith    }
12151973Smsmith    return(ENXIO);
12251973Smsmith}
12351973Smsmith
12451973Smsmithstatic int
12551973Smsmithmlx_pci_attach(device_t dev)
12651973Smsmith{
12751973Smsmith    struct mlx_softc	*sc;
128240608Sjhb    struct mlx_ident	*m;
129240608Sjhb    int			error;
13051973Smsmith
13158188Smsmith    debug_called(1);
13251973Smsmith
133240608Sjhb    pci_enable_busmaster(dev);
13451973Smsmith
13551973Smsmith    sc = device_get_softc(dev);
13651973Smsmith    sc->mlx_dev = dev;
13751973Smsmith
13851973Smsmith    /*
13951973Smsmith     * Work out what sort of adapter this is (we need to know this in order
14051973Smsmith     * to map the appropriate interface resources).
14151973Smsmith     */
142240608Sjhb    m = mlx_pci_match(dev);
143240608Sjhb    if (m == NULL)		/* shouldn't happen */
14451973Smsmith	return(ENXIO);
145240608Sjhb    sc->mlx_iftype = m->iftype;
146240608Sjhb
147240608Sjhb    mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF);
148240608Sjhb    sx_init(&sc->mlx_config_lock, "mlx config");
149240608Sjhb    callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0);
150240608Sjhb
15151973Smsmith    /*
15251973Smsmith     * Allocate the PCI register window.
15351973Smsmith     */
15451973Smsmith
15564223Smsmith    /* type 2/3 adapters have an I/O region we don't prefer at base 0 */
15658188Smsmith    switch(sc->mlx_iftype) {
15758188Smsmith    case MLX_IFTYPE_2:
15858188Smsmith    case MLX_IFTYPE_3:
15969292Smdodd	sc->mlx_mem_type = SYS_RES_MEMORY;
16069292Smdodd	sc->mlx_mem_rid = MLX_CFG_BASE1;
161127135Snjl	sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
162127135Snjl		&sc->mlx_mem_rid, RF_ACTIVE);
16364223Smsmith	if (sc->mlx_mem == NULL) {
16469292Smdodd	    sc->mlx_mem_type = SYS_RES_IOPORT;
16569292Smdodd	    sc->mlx_mem_rid = MLX_CFG_BASE0;
166127135Snjl	    sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
167127135Snjl		&sc->mlx_mem_rid, RF_ACTIVE);
16864223Smsmith	}
16958188Smsmith	break;
17058188Smsmith    case MLX_IFTYPE_4:
17158188Smsmith    case MLX_IFTYPE_5:
17269292Smdodd	sc->mlx_mem_type = SYS_RES_MEMORY;
17369292Smdodd	sc->mlx_mem_rid = MLX_CFG_BASE0;
174127135Snjl	sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type,
175127135Snjl		&sc->mlx_mem_rid, RF_ACTIVE);
17658188Smsmith	break;
17758188Smsmith    }
17851973Smsmith    if (sc->mlx_mem == NULL) {
17951973Smsmith	device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n");
18051973Smsmith	mlx_free(sc);
18151973Smsmith	return(ENXIO);
18251973Smsmith    }
18351973Smsmith
18451973Smsmith    /*
18551973Smsmith     * Allocate the parent bus DMA tag appropriate for PCI.
18651973Smsmith     */
187232854Sscottl    error = bus_dma_tag_create(bus_get_dma_tag(dev),	/* PCI parent */
18851973Smsmith			       1, 0, 			/* alignment, boundary */
18951973Smsmith			       BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
19051973Smsmith			       BUS_SPACE_MAXADDR, 	/* highaddr */
19151973Smsmith			       NULL, NULL, 		/* filter, filterarg */
19260074Smsmith			       MAXBSIZE, MLX_NSEG,	/* maxsize, nsegments */
19351973Smsmith			       BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
19451973Smsmith			       BUS_DMA_ALLOCNOW,	/* flags */
195117126Sscottl			       NULL,			/* lockfunc */
196117126Sscottl			       NULL,			/* lockarg */
19751973Smsmith			       &sc->mlx_parent_dmat);
19851973Smsmith    if (error != 0) {
19951973Smsmith	device_printf(dev, "can't allocate parent DMA tag\n");
20051973Smsmith	mlx_free(sc);
20151973Smsmith	return(ENOMEM);
20251973Smsmith    }
20351973Smsmith
20451973Smsmith    /*
20551973Smsmith     * Do bus-independant initialisation.
20651973Smsmith     */
20751973Smsmith    error = mlx_attach(sc);
208148570Scsjp    if (error != 0) {
209144161Sphk	mlx_free(sc);
21051973Smsmith	return(error);
211148570Scsjp    }
21251973Smsmith
21351973Smsmith    /*
21451973Smsmith     * Start the controller.
21551973Smsmith     */
21651973Smsmith    mlx_startup(sc);
21751973Smsmith    return(0);
21851973Smsmith}
219