11ac4b82bSMike Smith /*- 21ac4b82bSMike Smith * Copyright (c) 1999 Michael Smith 31ac4b82bSMike Smith * All rights reserved. 41ac4b82bSMike Smith * 51ac4b82bSMike Smith * Redistribution and use in source and binary forms, with or without 61ac4b82bSMike Smith * modification, are permitted provided that the following conditions 71ac4b82bSMike Smith * are met: 81ac4b82bSMike Smith * 1. Redistributions of source code must retain the above copyright 91ac4b82bSMike Smith * notice, this list of conditions and the following disclaimer. 101ac4b82bSMike Smith * 2. Redistributions in binary form must reproduce the above copyright 111ac4b82bSMike Smith * notice, this list of conditions and the following disclaimer in the 121ac4b82bSMike Smith * documentation and/or other materials provided with the distribution. 131ac4b82bSMike Smith * 141ac4b82bSMike Smith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151ac4b82bSMike Smith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161ac4b82bSMike Smith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171ac4b82bSMike Smith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181ac4b82bSMike Smith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191ac4b82bSMike Smith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201ac4b82bSMike Smith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211ac4b82bSMike Smith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221ac4b82bSMike Smith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231ac4b82bSMike Smith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241ac4b82bSMike Smith * SUCH DAMAGE. 251ac4b82bSMike Smith * 261ac4b82bSMike Smith * $FreeBSD$ 271ac4b82bSMike Smith */ 281ac4b82bSMike Smith 291ac4b82bSMike Smith #include <sys/param.h> 301ac4b82bSMike Smith #include <sys/systm.h> 311ac4b82bSMike Smith #include <sys/malloc.h> 321ac4b82bSMike Smith #include <sys/kernel.h> 331ac4b82bSMike Smith 341ac4b82bSMike Smith #include <sys/bus.h> 351ac4b82bSMike Smith #include <sys/buf.h> 361ac4b82bSMike Smith #include <sys/conf.h> 371ac4b82bSMike Smith #include <sys/devicestat.h> 381ac4b82bSMike Smith #include <sys/disk.h> 391ac4b82bSMike Smith 401ac4b82bSMike Smith #include <machine/bus_memio.h> 411ac4b82bSMike Smith #include <machine/bus_pio.h> 421ac4b82bSMike Smith #include <machine/bus.h> 431ac4b82bSMike Smith #include <machine/resource.h> 441ac4b82bSMike Smith #include <sys/rman.h> 451ac4b82bSMike Smith 461ac4b82bSMike Smith #include <pci/pcireg.h> 471ac4b82bSMike Smith #include <pci/pcivar.h> 481ac4b82bSMike Smith 491ac4b82bSMike Smith #include <dev/mlx/mlxio.h> 501ac4b82bSMike Smith #include <dev/mlx/mlxvar.h> 511ac4b82bSMike Smith 521ac4b82bSMike Smith #if 0 531ac4b82bSMike Smith #define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args) 541ac4b82bSMike Smith #else 551ac4b82bSMike Smith #define debug(fmt, args...) 561ac4b82bSMike Smith #endif 571ac4b82bSMike Smith 581ac4b82bSMike Smith static int mlx_pci_probe(device_t dev); 591ac4b82bSMike Smith static int mlx_pci_attach(device_t dev); 601ac4b82bSMike Smith 611ac4b82bSMike Smith static device_method_t mlx_methods[] = { 621ac4b82bSMike Smith /* Device interface */ 631ac4b82bSMike Smith DEVMETHOD(device_probe, mlx_pci_probe), 641ac4b82bSMike Smith DEVMETHOD(device_attach, mlx_pci_attach), 651ac4b82bSMike Smith DEVMETHOD(device_detach, mlx_detach), 661ac4b82bSMike Smith DEVMETHOD(device_shutdown, mlx_shutdown), 671ac4b82bSMike Smith DEVMETHOD(device_suspend, mlx_suspend), 681ac4b82bSMike Smith DEVMETHOD(device_resume, mlx_resume), 691ac4b82bSMike Smith 701ac4b82bSMike Smith DEVMETHOD(bus_print_child, bus_generic_print_child), 711ac4b82bSMike Smith DEVMETHOD(bus_driver_added, bus_generic_driver_added), 721ac4b82bSMike Smith { 0, 0 } 731ac4b82bSMike Smith }; 741ac4b82bSMike Smith 751ac4b82bSMike Smith static driver_t mlx_pci_driver = { 761ac4b82bSMike Smith "mlx", 771ac4b82bSMike Smith mlx_methods, 781ac4b82bSMike Smith sizeof(struct mlx_softc) 791ac4b82bSMike Smith }; 801ac4b82bSMike Smith 811ac4b82bSMike Smith DRIVER_MODULE(mlx, pci, mlx_pci_driver, mlx_devclass, 0, 0); 821ac4b82bSMike Smith 831ac4b82bSMike Smith struct 841ac4b82bSMike Smith { 851ac4b82bSMike Smith u_int16_t vendor; 861ac4b82bSMike Smith u_int16_t device; 871ac4b82bSMike Smith int iftype; 881ac4b82bSMike Smith char *desc; 891ac4b82bSMike Smith } mlx_identifiers[] = { 901ac4b82bSMike Smith {0x1069, 0x0002, MLX_IFTYPE_3, "Mylex version 3 RAID interface"}, /* Mylex v3 software interface */ 911ac4b82bSMike Smith {0, 0, 0, 0} 921ac4b82bSMike Smith }; 931ac4b82bSMike Smith 941ac4b82bSMike Smith static int 951ac4b82bSMike Smith mlx_pci_probe(device_t dev) 961ac4b82bSMike Smith { 971ac4b82bSMike Smith int i; 981ac4b82bSMike Smith 991ac4b82bSMike Smith debug("called"); 1001ac4b82bSMike Smith 1011ac4b82bSMike Smith for (i = 0; mlx_identifiers[i].vendor != 0; i++) { 1021ac4b82bSMike Smith if ((mlx_identifiers[i].vendor == pci_get_vendor(dev)) && 1031ac4b82bSMike Smith (mlx_identifiers[i].device == pci_get_device(dev))) { 1041ac4b82bSMike Smith 1051ac4b82bSMike Smith device_set_desc(dev, mlx_identifiers[i].desc); 1061ac4b82bSMike Smith return(0); 1071ac4b82bSMike Smith } 1081ac4b82bSMike Smith } 1091ac4b82bSMike Smith return(ENXIO); 1101ac4b82bSMike Smith } 1111ac4b82bSMike Smith 1121ac4b82bSMike Smith static int 1131ac4b82bSMike Smith mlx_pci_attach(device_t dev) 1141ac4b82bSMike Smith { 1151ac4b82bSMike Smith struct mlx_softc *sc; 1161ac4b82bSMike Smith int i, rid, error; 1171ac4b82bSMike Smith u_int32_t command; 1181ac4b82bSMike Smith 1191ac4b82bSMike Smith debug("called"); 1201ac4b82bSMike Smith 1211ac4b82bSMike Smith /* 1221ac4b82bSMike Smith * Make sure we are going to be able to talk to this board. 1231ac4b82bSMike Smith */ 1241ac4b82bSMike Smith command = pci_read_config(dev, PCIR_COMMAND, 1); 1251ac4b82bSMike Smith if ((command & PCIM_CMD_MEMEN) == 0) { 1261ac4b82bSMike Smith device_printf(dev, "memory window not available\n"); 1271ac4b82bSMike Smith return(ENXIO); 1281ac4b82bSMike Smith } 1291ac4b82bSMike Smith 1301ac4b82bSMike Smith /* 1311ac4b82bSMike Smith * Initialise softc. 1321ac4b82bSMike Smith */ 1331ac4b82bSMike Smith sc = device_get_softc(dev); 1341ac4b82bSMike Smith bzero(sc, sizeof(*sc)); 1351ac4b82bSMike Smith sc->mlx_dev = dev; 1361ac4b82bSMike Smith 1371ac4b82bSMike Smith /* 1381ac4b82bSMike Smith * Work out what sort of adapter this is (we need to know this in order 1391ac4b82bSMike Smith * to map the appropriate interface resources). 1401ac4b82bSMike Smith */ 1411ac4b82bSMike Smith sc->mlx_iftype = 0; 1421ac4b82bSMike Smith for (i = 0; mlx_identifiers[i].vendor != 0; i++) { 1431ac4b82bSMike Smith if ((mlx_identifiers[i].vendor == pci_get_vendor(dev)) && 1441ac4b82bSMike Smith (mlx_identifiers[i].device == pci_get_device(dev))) { 1451ac4b82bSMike Smith sc->mlx_iftype = mlx_identifiers[i].iftype; 1461ac4b82bSMike Smith break; 1471ac4b82bSMike Smith } 1481ac4b82bSMike Smith } 1491ac4b82bSMike Smith if (sc->mlx_iftype == 0) /* shouldn't happen */ 1501ac4b82bSMike Smith return(ENXIO); 1511ac4b82bSMike Smith 1521ac4b82bSMike Smith /* 1531ac4b82bSMike Smith * Allocate the PCI register window. 1541ac4b82bSMike Smith */ 1551ac4b82bSMike Smith 1561ac4b82bSMike Smith /* type 3 adapters have an I/O region we don't use at base 0 */ 1571ac4b82bSMike Smith rid = (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0; 1581ac4b82bSMike Smith sc->mlx_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, RF_ACTIVE); 1591ac4b82bSMike Smith if (sc->mlx_mem == NULL) { 1601ac4b82bSMike Smith device_printf(sc->mlx_dev, "couldn't allocate mailbox window\n"); 1611ac4b82bSMike Smith mlx_free(sc); 1621ac4b82bSMike Smith return(ENXIO); 1631ac4b82bSMike Smith } 1641ac4b82bSMike Smith sc->mlx_btag = rman_get_bustag(sc->mlx_mem); 1651ac4b82bSMike Smith sc->mlx_bhandle = rman_get_bushandle(sc->mlx_mem); 1661ac4b82bSMike Smith 1671ac4b82bSMike Smith /* 1681ac4b82bSMike Smith * Allocate the parent bus DMA tag appropriate for PCI. 1691ac4b82bSMike Smith */ 1701ac4b82bSMike Smith error = bus_dma_tag_create(NULL, /* parent */ 1711ac4b82bSMike Smith 1, 0, /* alignment, boundary */ 1721ac4b82bSMike Smith BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1731ac4b82bSMike Smith BUS_SPACE_MAXADDR, /* highaddr */ 1741ac4b82bSMike Smith NULL, NULL, /* filter, filterarg */ 1751ac4b82bSMike Smith MAXBSIZE, MLX_NSEG, /* maxsize, nsegments */ 1761ac4b82bSMike Smith BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1771ac4b82bSMike Smith BUS_DMA_ALLOCNOW, /* flags */ 1781ac4b82bSMike Smith &sc->mlx_parent_dmat); 1791ac4b82bSMike Smith if (error != 0) { 1801ac4b82bSMike Smith device_printf(dev, "can't allocate parent DMA tag\n"); 1811ac4b82bSMike Smith mlx_free(sc); 1821ac4b82bSMike Smith return(ENOMEM); 1831ac4b82bSMike Smith } 1841ac4b82bSMike Smith 1851ac4b82bSMike Smith /* 1861ac4b82bSMike Smith * Do bus-independant initialisation. 1871ac4b82bSMike Smith */ 1881ac4b82bSMike Smith error = mlx_attach(sc); 1891ac4b82bSMike Smith if (error != 0) { 1901ac4b82bSMike Smith mlx_free(sc); 1911ac4b82bSMike Smith return(error); 1921ac4b82bSMike Smith } 1931ac4b82bSMike Smith 1941ac4b82bSMike Smith /* 1951ac4b82bSMike Smith * Start the controller. 1961ac4b82bSMike Smith */ 1971ac4b82bSMike Smith mlx_startup(sc); 1981ac4b82bSMike Smith return(0); 1991ac4b82bSMike Smith } 200