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