11ac4b82bSMike Smith /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3718cf2ccSPedro F. Giffuni * 41ac4b82bSMike Smith * Copyright (c) 1999 Michael Smith 51ac4b82bSMike Smith * All rights reserved. 61ac4b82bSMike Smith * 71ac4b82bSMike Smith * Redistribution and use in source and binary forms, with or without 81ac4b82bSMike Smith * modification, are permitted provided that the following conditions 91ac4b82bSMike Smith * are met: 101ac4b82bSMike Smith * 1. Redistributions of source code must retain the above copyright 111ac4b82bSMike Smith * notice, this list of conditions and the following disclaimer. 121ac4b82bSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 131ac4b82bSMike Smith * notice, this list of conditions and the following disclaimer in the 141ac4b82bSMike Smith * documentation and/or other materials provided with the distribution. 151ac4b82bSMike Smith * 161ac4b82bSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 171ac4b82bSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 181ac4b82bSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 191ac4b82bSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 201ac4b82bSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 211ac4b82bSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 221ac4b82bSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 231ac4b82bSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 241ac4b82bSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 251ac4b82bSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261ac4b82bSMike Smith * SUCH DAMAGE. 271ac4b82bSMike Smith */ 281ac4b82bSMike Smith 29aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 30aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 31aad970f1SDavid E. O'Brien 321ac4b82bSMike Smith #include <sys/param.h> 331ac4b82bSMike Smith #include <sys/systm.h> 34b04e4c12SJohn Baldwin #include <sys/bio.h> 351ac4b82bSMike Smith #include <sys/kernel.h> 360fca6f8bSJohn Baldwin #include <sys/lock.h> 37fe12f24bSPoul-Henning Kamp #include <sys/module.h> 380fca6f8bSJohn Baldwin #include <sys/mutex.h> 390fca6f8bSJohn Baldwin #include <sys/sx.h> 401ac4b82bSMike Smith 411ac4b82bSMike Smith #include <sys/bus.h> 421ac4b82bSMike Smith #include <sys/conf.h> 431ac4b82bSMike Smith 441ac4b82bSMike Smith #include <machine/bus.h> 451ac4b82bSMike Smith #include <machine/resource.h> 461ac4b82bSMike Smith #include <sys/rman.h> 471ac4b82bSMike Smith 48891619a6SPoul-Henning Kamp #include <geom/geom_disk.h> 49891619a6SPoul-Henning Kamp 5038d8c994SWarner Losh #include <dev/pci/pcireg.h> 5138d8c994SWarner Losh #include <dev/pci/pcivar.h> 521ac4b82bSMike Smith 531ac4b82bSMike Smith #include <dev/mlx/mlxio.h> 541ac4b82bSMike Smith #include <dev/mlx/mlxvar.h> 554b006d7bSMike Smith #include <dev/mlx/mlxreg.h> 561ac4b82bSMike Smith 571ac4b82bSMike Smith static int mlx_pci_probe(device_t dev); 581ac4b82bSMike Smith static int mlx_pci_attach(device_t dev); 591ac4b82bSMike Smith 601ac4b82bSMike Smith static device_method_t mlx_methods[] = { 611ac4b82bSMike Smith /* Device interface */ 621ac4b82bSMike Smith DEVMETHOD(device_probe, mlx_pci_probe), 631ac4b82bSMike Smith DEVMETHOD(device_attach, mlx_pci_attach), 641ac4b82bSMike Smith DEVMETHOD(device_detach, mlx_detach), 651ac4b82bSMike Smith DEVMETHOD(device_shutdown, mlx_shutdown), 661ac4b82bSMike Smith DEVMETHOD(device_suspend, mlx_suspend), 671ac4b82bSMike Smith DEVMETHOD(device_resume, mlx_resume), 681ac4b82bSMike Smith 694b7ec270SMarius Strobl DEVMETHOD_END 701ac4b82bSMike Smith }; 711ac4b82bSMike Smith 721ac4b82bSMike Smith static driver_t mlx_pci_driver = { 731ac4b82bSMike Smith "mlx", 741ac4b82bSMike Smith mlx_methods, 751ac4b82bSMike Smith sizeof(struct mlx_softc) 761ac4b82bSMike Smith }; 771ac4b82bSMike Smith 789cd54db5SJohn Baldwin DRIVER_MODULE(mlx, pci, mlx_pci_driver, 0, 0); 791ac4b82bSMike Smith 805792b7feSMike Smith struct mlx_ident 811ac4b82bSMike Smith { 821ac4b82bSMike Smith u_int16_t vendor; 831ac4b82bSMike Smith u_int16_t device; 845792b7feSMike Smith u_int16_t subvendor; 855792b7feSMike Smith u_int16_t subdevice; 861ac4b82bSMike Smith int iftype; 871ac4b82bSMike Smith char *desc; 881ac4b82bSMike Smith } mlx_identifiers[] = { 89da8bb3a3SMike Smith {0x1069, 0x0001, 0x0000, 0x0000, MLX_IFTYPE_2, "Mylex version 2 RAID interface"}, 905792b7feSMike Smith {0x1069, 0x0002, 0x0000, 0x0000, MLX_IFTYPE_3, "Mylex version 3 RAID interface"}, 915792b7feSMike Smith {0x1069, 0x0010, 0x0000, 0x0000, MLX_IFTYPE_4, "Mylex version 4 RAID interface"}, 925792b7feSMike Smith {0x1011, 0x1065, 0x1069, 0x0020, MLX_IFTYPE_5, "Mylex version 5 RAID interface"}, 935792b7feSMike Smith {0, 0, 0, 0, 0, 0} 941ac4b82bSMike Smith }; 951ac4b82bSMike Smith 960fca6f8bSJohn Baldwin static struct mlx_ident * 970fca6f8bSJohn Baldwin mlx_pci_match(device_t dev) 980fca6f8bSJohn Baldwin { 990fca6f8bSJohn Baldwin struct mlx_ident *m; 1000fca6f8bSJohn Baldwin 1010fca6f8bSJohn Baldwin for (m = mlx_identifiers; m->vendor != 0; m++) { 1020fca6f8bSJohn Baldwin if ((m->vendor == pci_get_vendor(dev)) && 1030fca6f8bSJohn Baldwin (m->device == pci_get_device(dev)) && 1040fca6f8bSJohn Baldwin ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && 1050fca6f8bSJohn Baldwin (m->subdevice == pci_get_subdevice(dev))))) 1060fca6f8bSJohn Baldwin return (m); 1070fca6f8bSJohn Baldwin } 1080fca6f8bSJohn Baldwin return (NULL); 1090fca6f8bSJohn Baldwin } 1100fca6f8bSJohn Baldwin 1111ac4b82bSMike Smith static int 1121ac4b82bSMike Smith mlx_pci_probe(device_t dev) 1131ac4b82bSMike Smith { 1145792b7feSMike Smith struct mlx_ident *m; 1151ac4b82bSMike Smith 116da8bb3a3SMike Smith debug_called(1); 1171ac4b82bSMike Smith 1180fca6f8bSJohn Baldwin m = mlx_pci_match(dev); 1190fca6f8bSJohn Baldwin if (m != NULL) { 1205792b7feSMike Smith device_set_desc(dev, m->desc); 1216b9907e7SWarner Losh return(BUS_PROBE_DEFAULT); 1221ac4b82bSMike Smith } 1231ac4b82bSMike Smith return(ENXIO); 1241ac4b82bSMike Smith } 1251ac4b82bSMike Smith 1261ac4b82bSMike Smith static int 1271ac4b82bSMike Smith mlx_pci_attach(device_t dev) 1281ac4b82bSMike Smith { 1291ac4b82bSMike Smith struct mlx_softc *sc; 1300fca6f8bSJohn Baldwin struct mlx_ident *m; 1310fca6f8bSJohn Baldwin int error; 1321ac4b82bSMike Smith 133da8bb3a3SMike Smith debug_called(1); 1341ac4b82bSMike Smith 1350fca6f8bSJohn Baldwin pci_enable_busmaster(dev); 1361ac4b82bSMike Smith 1371ac4b82bSMike Smith sc = device_get_softc(dev); 1381ac4b82bSMike Smith sc->mlx_dev = dev; 1391ac4b82bSMike Smith 1401ac4b82bSMike Smith /* 1411ac4b82bSMike Smith * Work out what sort of adapter this is (we need to know this in order 1421ac4b82bSMike Smith * to map the appropriate interface resources). 1431ac4b82bSMike Smith */ 1440fca6f8bSJohn Baldwin m = mlx_pci_match(dev); 1450fca6f8bSJohn Baldwin if (m == NULL) /* shouldn't happen */ 1461ac4b82bSMike Smith return(ENXIO); 1470fca6f8bSJohn Baldwin sc->mlx_iftype = m->iftype; 1480fca6f8bSJohn Baldwin 1490fca6f8bSJohn Baldwin mtx_init(&sc->mlx_io_lock, "mlx I/O", NULL, MTX_DEF); 1500fca6f8bSJohn Baldwin sx_init(&sc->mlx_config_lock, "mlx config"); 1510fca6f8bSJohn Baldwin callout_init_mtx(&sc->mlx_timeout, &sc->mlx_io_lock, 0); 1521ac4b82bSMike Smith 1531ac4b82bSMike Smith /* 1541ac4b82bSMike Smith * Allocate the PCI register window. 1551ac4b82bSMike Smith */ 1561ac4b82bSMike Smith 157786cd128SMike Smith /* type 2/3 adapters have an I/O region we don't prefer at base 0 */ 158da8bb3a3SMike Smith switch(sc->mlx_iftype) { 159da8bb3a3SMike Smith case MLX_IFTYPE_2: 160da8bb3a3SMike Smith case MLX_IFTYPE_3: 1619b11c7baSMatthew N. Dodd sc->mlx_mem_type = SYS_RES_MEMORY; 1629b11c7baSMatthew N. Dodd sc->mlx_mem_rid = MLX_CFG_BASE1; 1635f96beb9SNate Lawson sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, 1645f96beb9SNate Lawson &sc->mlx_mem_rid, RF_ACTIVE); 165786cd128SMike Smith if (sc->mlx_mem == NULL) { 1669b11c7baSMatthew N. Dodd sc->mlx_mem_type = SYS_RES_IOPORT; 1679b11c7baSMatthew N. Dodd sc->mlx_mem_rid = MLX_CFG_BASE0; 1685f96beb9SNate Lawson sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, 1695f96beb9SNate Lawson &sc->mlx_mem_rid, RF_ACTIVE); 170786cd128SMike Smith } 171da8bb3a3SMike Smith break; 172da8bb3a3SMike Smith case MLX_IFTYPE_4: 173da8bb3a3SMike Smith case MLX_IFTYPE_5: 1749b11c7baSMatthew N. Dodd sc->mlx_mem_type = SYS_RES_MEMORY; 1759b11c7baSMatthew N. Dodd sc->mlx_mem_rid = MLX_CFG_BASE0; 1765f96beb9SNate Lawson sc->mlx_mem = bus_alloc_resource_any(dev, sc->mlx_mem_type, 1775f96beb9SNate Lawson &sc->mlx_mem_rid, RF_ACTIVE); 178da8bb3a3SMike Smith break; 179da8bb3a3SMike Smith } 1801ac4b82bSMike Smith if (sc->mlx_mem == NULL) { 1811ac4b82bSMike Smith device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n"); 1821ac4b82bSMike Smith mlx_free(sc); 1831ac4b82bSMike Smith return(ENXIO); 1841ac4b82bSMike Smith } 1851ac4b82bSMike Smith 1861ac4b82bSMike Smith /* 1871ac4b82bSMike Smith * Allocate the parent bus DMA tag appropriate for PCI. 1881ac4b82bSMike Smith */ 189b6f97155SScott Long error = bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ 1901ac4b82bSMike Smith 1, 0, /* alignment, boundary */ 1911ac4b82bSMike Smith BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1921ac4b82bSMike Smith BUS_SPACE_MAXADDR, /* highaddr */ 1931ac4b82bSMike Smith NULL, NULL, /* filter, filterarg */ 1946f954fb3SAlexander Motin BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 1956f954fb3SAlexander Motin BUS_SPACE_UNRESTRICTED, /* nsegments */ 1961ac4b82bSMike Smith BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1971ac4b82bSMike Smith BUS_DMA_ALLOCNOW, /* flags */ 198f6b1c44dSScott Long NULL, /* lockfunc */ 199f6b1c44dSScott Long NULL, /* lockarg */ 2001ac4b82bSMike Smith &sc->mlx_parent_dmat); 2011ac4b82bSMike Smith if (error != 0) { 2021ac4b82bSMike Smith device_printf(dev, "can't allocate parent DMA tag\n"); 2031ac4b82bSMike Smith mlx_free(sc); 2041ac4b82bSMike Smith return(ENOMEM); 2051ac4b82bSMike Smith } 2061ac4b82bSMike Smith 2071ac4b82bSMike Smith /* 2089ae6b386SGordon Bergling * Do bus-independent initialisation. 2091ac4b82bSMike Smith */ 2101ac4b82bSMike Smith error = mlx_attach(sc); 211648fd2bdSChristian S.J. Peron if (error != 0) { 21223db907cSPoul-Henning Kamp mlx_free(sc); 2131ac4b82bSMike Smith return(error); 214648fd2bdSChristian S.J. Peron } 2151ac4b82bSMike Smith 2161ac4b82bSMike Smith /* 2171ac4b82bSMike Smith * Start the controller. 2181ac4b82bSMike Smith */ 2191ac4b82bSMike Smith mlx_startup(sc); 2201ac4b82bSMike Smith return(0); 2211ac4b82bSMike Smith } 222