mpt_pci.c revision 166901
138363Swpaul/*- 238363Swpaul * PCI specific probe and attach routines for LSI Fusion Adapters 338363Swpaul * FreeBSD Version. 438363Swpaul * 538363Swpaul * Copyright (c) 2000, 2001 by Greg Ansley 638363Swpaul * Partially derived from Matt Jacob's ISP driver. 738363Swpaul * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob 838363Swpaul * Feral Software 938363Swpaul * All rights reserved. 1038363Swpaul * 1138363Swpaul * Redistribution and use in source and binary forms, with or without 1238363Swpaul * modification, are permitted provided that the following conditions 1338363Swpaul * are met: 1438363Swpaul * 1. Redistributions of source code must retain the above copyright 1538363Swpaul * notice immediately at the beginning of the file, without modification, 1638363Swpaul * this list of conditions, and the following disclaimer. 1738363Swpaul * 2. The name of the author may not be used to endorse or promote products 1838363Swpaul * derived from this software without specific prior written permission. 1938363Swpaul * 2038363Swpaul * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2138363Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2238363Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2338363Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2438363Swpaul * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2538363Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2638363Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2738363Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2838363Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2938363Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3038363Swpaul * SUCH DAMAGE. 3138363Swpaul */ 3250477Speter/*- 3338363Swpaul * Copyright (c) 2002, 2006 by Matthew Jacob 3438363Swpaul * All rights reserved. 3538363Swpaul * 3638363Swpaul * Redistribution and use in source and binary forms, with or without 3738363Swpaul * modification, are permitted provided that the following conditions are 3838363Swpaul * met: 3967233Simp * 1. Redistributions of source code must retain the above copyright 4038363Swpaul * notice, this list of conditions and the following disclaimer. 4138363Swpaul * 2. Redistributions in binary form must reproduce at minimum a disclaimer 4238363Swpaul * substantially similar to the "NO WARRANTY" disclaimer below 4338363Swpaul * ("Disclaimer") and any redistribution must be conditioned upon including 4438363Swpaul * a substantially similar Disclaimer requirement for further binary 4538363Swpaul * redistribution. 4638363Swpaul * 3. Neither the names of the above listed copyright holders nor the names 4738363Swpaul * of any contributors may be used to endorse or promote products derived 4838363Swpaul * from this software without specific prior written permission. 4938363Swpaul * 5038363Swpaul * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 5138363Swpaul * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5238363Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5338363Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 5438363Swpaul * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5538363Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5638363Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5738363Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 5838363Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5938363Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 6038363Swpaul * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6138363Swpaul * 6238363Swpaul * Support from Chris Ellsworth in order to make SAS adapters work 6338363Swpaul * is gratefully acknowledged. 6438363Swpaul * 6538363Swpaul * Support from LSI-Logic has also gone a great deal toward making this a 6638363Swpaul * workable subsystem and is gratefully acknowledged. 6738363Swpaul */ 6838363Swpaul/* 6938363Swpaul * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 7038363Swpaul * Copyright (c) 2005, WHEEL Sp. z o.o. 7138363Swpaul * Copyright (c) 2004, 2005 Justin T. Gibbs 7238363Swpaul * All rights reserved. 7338363Swpaul * 7438363Swpaul * Redistribution and use in source and binary forms, with or without 7538363Swpaul * modification, are permitted provided that the following conditions are 7638363Swpaul * met: 7738363Swpaul * 1. Redistributions of source code must retain the above copyright 7838363Swpaul * notice, this list of conditions and the following disclaimer. 7938363Swpaul * 2. Redistributions in binary form must reproduce at minimum a disclaimer 8038363Swpaul * substantially similar to the "NO WARRANTY" disclaimer below 8138363Swpaul * ("Disclaimer") and any redistribution must be conditioned upon including 8238363Swpaul * a substantially similar Disclaimer requirement for further binary 8338363Swpaul * redistribution. 8477548Swpaul * 3. Neither the names of the above listed copyright holders nor the names 8538363Swpaul * of any contributors may be used to endorse or promote products derived 8638363Swpaul * from this software without specific prior written permission. 8738363Swpaul * 8838363Swpaul * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 8938363Swpaul * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9038363Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9138363Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 9238363Swpaul * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 9338363Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 9438363Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 9538363Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9651441Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 9738363Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 9838363Swpaul * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9938363Swpaul */ 10051441Swpaul 10138363Swpaul#include <sys/cdefs.h> 10238363Swpaul__FBSDID("$FreeBSD: head/sys/dev/mpt/mpt_pci.c 166901 2007-02-23 12:19:07Z piso $"); 10338363Swpaul 10438363Swpaul#include <dev/mpt/mpt.h> 10538363Swpaul#include <dev/mpt/mpt_cam.h> 10638363Swpaul#include <dev/mpt/mpt_raid.h> 10738363Swpaul 10838363Swpaul#if __FreeBSD_version < 700000 10938363Swpaul#define pci_msix_count(x) 0 11038363Swpaul#define pci_msi_count(x) 0 11138363Swpaul#define pci_alloc_msi(x, y) 1 11238363Swpaul#define pci_alloc_msix(x, y) 1 11338363Swpaul#define pci_release_msi(x) do { ; } while (0) 11438363Swpaul#endif 11538363Swpaul 11638363Swpaul#ifndef PCI_VENDOR_LSI 11738363Swpaul#define PCI_VENDOR_LSI 0x1000 11838363Swpaul#endif 11938363Swpaul 12038363Swpaul#ifndef PCI_PRODUCT_LSI_FC909 12138363Swpaul#define PCI_PRODUCT_LSI_FC909 0x0620 12238363Swpaul#endif 12338363Swpaul 12438363Swpaul#ifndef PCI_PRODUCT_LSI_FC909A 12538363Swpaul#define PCI_PRODUCT_LSI_FC909A 0x0621 12638363Swpaul#endif 12738363Swpaul 12838363Swpaul#ifndef PCI_PRODUCT_LSI_FC919 12938363Swpaul#define PCI_PRODUCT_LSI_FC919 0x0624 13038363Swpaul#endif 13138363Swpaul 13238363Swpaul#ifndef PCI_PRODUCT_LSI_FC929 13338363Swpaul#define PCI_PRODUCT_LSI_FC929 0x0622 13438363Swpaul#endif 13538363Swpaul 13638363Swpaul#ifndef PCI_PRODUCT_LSI_FC929X 13738363Swpaul#define PCI_PRODUCT_LSI_FC929X 0x0626 13838363Swpaul#endif 13938363Swpaul 14038363Swpaul#ifndef PCI_PRODUCT_LSI_FC919X 14138363Swpaul#define PCI_PRODUCT_LSI_FC919X 0x0628 14238363Swpaul#endif 14338363Swpaul 14438363Swpaul#ifndef PCI_PRODUCT_LSI_FC7X04X 14538363Swpaul#define PCI_PRODUCT_LSI_FC7X04X 0x0640 14638363Swpaul#endif 14738363Swpaul 14838363Swpaul#ifndef PCI_PRODUCT_LSI_FC646 14938363Swpaul#define PCI_PRODUCT_LSI_FC646 0x0646 15038363Swpaul#endif 15138363Swpaul 15238363Swpaul#ifndef PCI_PRODUCT_LSI_1030 15338363Swpaul#define PCI_PRODUCT_LSI_1030 0x0030 15438363Swpaul#endif 15538363Swpaul 15638363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1064 15738363Swpaul#define PCI_PRODUCT_LSI_SAS1064 0x0050 15838363Swpaul#endif 15938363Swpaul 16038363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1064A 16138363Swpaul#define PCI_PRODUCT_LSI_SAS1064A 0x005C 16238363Swpaul#endif 16338363Swpaul 16438363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1064E 16538363Swpaul#define PCI_PRODUCT_LSI_SAS1064E 0x0056 16638363Swpaul#endif 16738363Swpaul 16838363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1066 16938363Swpaul#define PCI_PRODUCT_LSI_SAS1066 0x005E 17038363Swpaul#endif 17138363Swpaul 17238363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1066E 17338363Swpaul#define PCI_PRODUCT_LSI_SAS1066E 0x005A 17438363Swpaul#endif 17538363Swpaul 17638363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1068 17738526Swpaul#define PCI_PRODUCT_LSI_SAS1068 0x0054 17838526Swpaul#endif 17938526Swpaul 18088079Ssilby#ifndef PCI_PRODUCT_LSI_SAS1068E 18138526Swpaul#define PCI_PRODUCT_LSI_SAS1068E 0x0058 18238526Swpaul#endif 18338526Swpaul 18438363Swpaul#ifndef PCI_PRODUCT_LSI_SAS1078 18538363Swpaul#define PCI_PRODUCT_LSI_SAS1078 0x0060 18638363Swpaul#endif 18738363Swpaul 18838363Swpaul#ifndef PCIM_CMD_SERRESPEN 18938363Swpaul#define PCIM_CMD_SERRESPEN 0x0100 19038363Swpaul#endif 19138363Swpaul 19238363Swpaul 19338363Swpaul#define MPT_IO_BAR 0 19438363Swpaul#define MPT_MEM_BAR 1 19538363Swpaul 19638363Swpaulstatic int mpt_pci_probe(device_t); 19738363Swpaulstatic int mpt_pci_attach(device_t); 19838363Swpaulstatic void mpt_free_bus_resources(struct mpt_softc *mpt); 19938363Swpaulstatic int mpt_pci_detach(device_t); 20038363Swpaulstatic int mpt_pci_shutdown(device_t); 20138363Swpaulstatic int mpt_dma_mem_alloc(struct mpt_softc *mpt); 20238363Swpaulstatic void mpt_dma_mem_free(struct mpt_softc *mpt); 20338363Swpaulstatic void mpt_read_config_regs(struct mpt_softc *mpt); 20438363Swpaulstatic void mpt_pci_intr(void *); 20538363Swpaul 20638363Swpaulstatic device_method_t mpt_methods[] = { 20738363Swpaul /* Device interface */ 20838363Swpaul DEVMETHOD(device_probe, mpt_pci_probe), 20938363Swpaul DEVMETHOD(device_attach, mpt_pci_attach), 21038363Swpaul DEVMETHOD(device_detach, mpt_pci_detach), 21138363Swpaul DEVMETHOD(device_shutdown, mpt_pci_shutdown), 21238363Swpaul { 0, 0 } 21338363Swpaul}; 21438363Swpaul 21538363Swpaulstatic driver_t mpt_driver = { 21638363Swpaul "mpt", mpt_methods, sizeof(struct mpt_softc) 21738363Swpaul}; 21838363Swpaulstatic devclass_t mpt_devclass; 21938363SwpaulDRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0); 22038363SwpaulMODULE_DEPEND(mpt, pci, 1, 1, 1); 22138363SwpaulMODULE_VERSION(mpt, 1); 22238363Swpaul 22338363Swpaulstatic int 22438363Swpaulmpt_pci_probe(device_t dev) 22538363Swpaul{ 22638363Swpaul char *desc; 22738363Swpaul 22838363Swpaul if (pci_get_vendor(dev) != PCI_VENDOR_LSI) { 22938363Swpaul return (ENXIO); 23038363Swpaul } 23138363Swpaul 23238363Swpaul switch ((pci_get_device(dev) & ~1)) { 23338363Swpaul case PCI_PRODUCT_LSI_FC909: 23438363Swpaul desc = "LSILogic FC909 FC Adapter"; 23538363Swpaul break; 23638363Swpaul case PCI_PRODUCT_LSI_FC909A: 23738363Swpaul desc = "LSILogic FC909A FC Adapter"; 23838363Swpaul break; 23938363Swpaul case PCI_PRODUCT_LSI_FC919: 24038363Swpaul desc = "LSILogic FC919 FC Adapter"; 24138363Swpaul break; 24238363Swpaul case PCI_PRODUCT_LSI_FC929: 24338363Swpaul desc = "Dual LSILogic FC929 FC Adapter"; 24438363Swpaul break; 24538363Swpaul case PCI_PRODUCT_LSI_FC919X: 24638363Swpaul desc = "LSILogic FC919 FC PCI-X Adapter"; 24738363Swpaul break; 24838363Swpaul case PCI_PRODUCT_LSI_FC929X: 24938363Swpaul desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter"; 25038363Swpaul break; 25138363Swpaul case PCI_PRODUCT_LSI_FC646: 25267233Simp desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter"; 25367233Simp break; 25467233Simp case PCI_PRODUCT_LSI_FC7X04X: 25538363Swpaul desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter"; 25638363Swpaul break; 25738363Swpaul case PCI_PRODUCT_LSI_1030: 25838363Swpaul desc = "LSILogic 1030 Ultra4 Adapter"; 25977548Swpaul break; 26038363Swpaul case PCI_PRODUCT_LSI_SAS1064: 26138363Swpaul case PCI_PRODUCT_LSI_SAS1064A: 26238363Swpaul case PCI_PRODUCT_LSI_SAS1064E: 26338363Swpaul case PCI_PRODUCT_LSI_SAS1066: 26438363Swpaul case PCI_PRODUCT_LSI_SAS1066E: 26538363Swpaul case PCI_PRODUCT_LSI_SAS1068: 26638363Swpaul case PCI_PRODUCT_LSI_SAS1068E: 26738363Swpaul case PCI_PRODUCT_LSI_SAS1078: 26838363Swpaul desc = "LSILogic SAS/SATA Adapter"; 26938363Swpaul break; 27038363Swpaul default: 27138363Swpaul return (ENXIO); 27238363Swpaul } 27338363Swpaul 27438363Swpaul device_set_desc(dev, desc); 27538363Swpaul return (0); 27638363Swpaul} 27738363Swpaul 27838363Swpaul#if __FreeBSD_version < 500000 27938363Swpaulstatic void 28038363Swpaulmpt_set_options(struct mpt_softc *mpt) 28138363Swpaul{ 28238363Swpaul int bitmap; 28338363Swpaul 28438363Swpaul bitmap = 0; 28538363Swpaul if (getenv_int("mpt_disable", &bitmap)) { 28638363Swpaul if (bitmap & (1 << mpt->unit)) { 28738363Swpaul mpt->disabled = 1; 28838363Swpaul } 28938363Swpaul } 29038363Swpaul bitmap = 0; 29138363Swpaul if (getenv_int("mpt_debug", &bitmap)) { 29238363Swpaul if (bitmap & (1 << mpt->unit)) { 29338363Swpaul mpt->verbose = MPT_PRT_DEBUG; 29438363Swpaul } 29538363Swpaul } 29638363Swpaul bitmap = 0; 29738363Swpaul if (getenv_int("mpt_debug1", &bitmap)) { 29838363Swpaul if (bitmap & (1 << mpt->unit)) { 29938363Swpaul mpt->verbose = MPT_PRT_DEBUG1; 30038363Swpaul } 30138363Swpaul } 30238363Swpaul bitmap = 0; 30338363Swpaul if (getenv_int("mpt_debug2", &bitmap)) { 30438363Swpaul if (bitmap & (1 << mpt->unit)) { 30538363Swpaul mpt->verbose = MPT_PRT_DEBUG2; 30638363Swpaul } 30738363Swpaul } 30838363Swpaul bitmap = 0; 30938363Swpaul if (getenv_int("mpt_debug3", &bitmap)) { 31038363Swpaul if (bitmap & (1 << mpt->unit)) { 31138363Swpaul mpt->verbose = MPT_PRT_DEBUG3; 31238363Swpaul } 31338363Swpaul } 31438363Swpaul 31538363Swpaul mpt->cfg_role = MPT_ROLE_DEFAULT; 31638363Swpaul bitmap = 0; 31738363Swpaul if (getenv_int("mpt_nil_role", &bitmap)) { 31838363Swpaul if (bitmap & (1 << mpt->unit)) { 31938363Swpaul mpt->cfg_role = 0; 32038363Swpaul } 32138363Swpaul mpt->do_cfg_role = 1; 32238363Swpaul } 32338363Swpaul bitmap = 0; 32438363Swpaul if (getenv_int("mpt_tgt_role", &bitmap)) { 32538363Swpaul if (bitmap & (1 << mpt->unit)) { 32638363Swpaul mpt->cfg_role |= MPT_ROLE_TARGET; 32738363Swpaul } 32838363Swpaul mpt->do_cfg_role = 1; 32938363Swpaul } 33038363Swpaul bitmap = 0; 33138363Swpaul if (getenv_int("mpt_ini_role", &bitmap)) { 33238363Swpaul if (bitmap & (1 << mpt->unit)) { 33338363Swpaul mpt->cfg_role |= MPT_ROLE_INITIATOR; 33438363Swpaul } 33538363Swpaul mpt->do_cfg_role = 1; 33638363Swpaul } 33738363Swpaul mpt->msi_enable = 0; 33838363Swpaul} 33938363Swpaul#else 34038363Swpaulstatic void 34138363Swpaulmpt_set_options(struct mpt_softc *mpt) 34238363Swpaul{ 34338363Swpaul int tval; 34438363Swpaul 34538363Swpaul tval = 0; 34638363Swpaul if (resource_int_value(device_get_name(mpt->dev), 34738363Swpaul device_get_unit(mpt->dev), "disable", &tval) == 0 && tval != 0) { 34838363Swpaul mpt->disabled = 1; 34938363Swpaul } 35038363Swpaul tval = 0; 35138363Swpaul if (resource_int_value(device_get_name(mpt->dev), 35238363Swpaul device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { 35338363Swpaul mpt->verbose = tval; 35438363Swpaul } 35538363Swpaul tval = -1; 35638363Swpaul if (resource_int_value(device_get_name(mpt->dev), 35738363Swpaul device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && 35838363Swpaul tval <= 3) { 35938363Swpaul mpt->cfg_role = tval; 36038363Swpaul mpt->do_cfg_role = 1; 36138363Swpaul } 36238363Swpaul 36338363Swpaul tval = 0; 36438363Swpaul mpt->msi_enable = 0; 36538363Swpaul if (resource_int_value(device_get_name(mpt->dev), 36638363Swpaul device_get_unit(mpt->dev), "msi_enable", &tval) == 0 && tval == 1) { 36738363Swpaul mpt->msi_enable = 1; 36838363Swpaul } 36938363Swpaul} 37038363Swpaul#endif 37140588Swpaul 37238363Swpaul 37338363Swpaulstatic void 37438363Swpaulmpt_link_peer(struct mpt_softc *mpt) 37538363Swpaul{ 37638363Swpaul struct mpt_softc *mpt2; 37738363Swpaul 37838363Swpaul if (mpt->unit == 0) { 37938363Swpaul return; 38038363Swpaul } 38138363Swpaul /* 38238363Swpaul * XXX: depends on probe order 38338363Swpaul */ 38438363Swpaul mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1); 38538363Swpaul 38638363Swpaul if (mpt2 == NULL) { 38738363Swpaul return; 38838363Swpaul } 38938363Swpaul if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) { 39038363Swpaul return; 39138363Swpaul } 39238363Swpaul if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) { 39338363Swpaul return; 39438363Swpaul } 39538363Swpaul mpt->mpt2 = mpt2; 39638363Swpaul mpt2->mpt2 = mpt; 39738363Swpaul if (mpt->verbose >= MPT_PRT_DEBUG) { 39838363Swpaul mpt_prt(mpt, "linking with peer (mpt%d)\n", 39938363Swpaul device_get_unit(mpt2->dev)); 40038363Swpaul } 40138363Swpaul} 40238363Swpaul 40338363Swpaulstatic void 40438363Swpaulmpt_unlink_peer(struct mpt_softc *mpt) 40538363Swpaul{ 40638363Swpaul if (mpt->mpt2) { 40738363Swpaul mpt->mpt2->mpt2 = NULL; 40838363Swpaul } 40938363Swpaul} 41038363Swpaul 41138363Swpaul 41238363Swpaulstatic int 41338363Swpaulmpt_pci_attach(device_t dev) 41438363Swpaul{ 41538363Swpaul struct mpt_softc *mpt; 41638363Swpaul int iqd; 41738363Swpaul uint32_t data, cmd; 41838363Swpaul 41938363Swpaul /* Allocate the softc structure */ 42038363Swpaul mpt = (struct mpt_softc*)device_get_softc(dev); 42138363Swpaul if (mpt == NULL) { 42238363Swpaul device_printf(dev, "cannot allocate softc\n"); 423107959Smux return (ENOMEM); 424107959Smux } 425107959Smux memset(mpt, 0, sizeof(struct mpt_softc)); 426107959Smux switch ((pci_get_device(dev) & ~1)) { 427107959Smux case PCI_PRODUCT_LSI_FC909: 428107959Smux case PCI_PRODUCT_LSI_FC909A: 429107959Smux case PCI_PRODUCT_LSI_FC919: 430107959Smux case PCI_PRODUCT_LSI_FC929: 431107959Smux case PCI_PRODUCT_LSI_FC919X: 43238363Swpaul case PCI_PRODUCT_LSI_FC646: 43338363Swpaul case PCI_PRODUCT_LSI_FC7X04X: 43438363Swpaul mpt->is_fc = 1; 43538363Swpaul break; 43638363Swpaul case PCI_PRODUCT_LSI_SAS1064: 43738363Swpaul case PCI_PRODUCT_LSI_SAS1064A: 43838363Swpaul case PCI_PRODUCT_LSI_SAS1064E: 43938363Swpaul case PCI_PRODUCT_LSI_SAS1066: 44038363Swpaul case PCI_PRODUCT_LSI_SAS1066E: 44138363Swpaul case PCI_PRODUCT_LSI_SAS1068: 44238363Swpaul case PCI_PRODUCT_LSI_SAS1068E: 44338363Swpaul case PCI_PRODUCT_LSI_SAS1078: 44438363Swpaul mpt->is_sas = 1; 44538363Swpaul break; 446107959Smux default: 44738363Swpaul mpt->is_spi = 1; 44838363Swpaul break; 44938363Swpaul } 45038363Swpaul mpt->dev = dev; 45138363Swpaul mpt->unit = device_get_unit(dev); 45238363Swpaul mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT; 45338363Swpaul mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; 45438363Swpaul mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; 45538363Swpaul mpt->verbose = MPT_PRT_NONE; 456107959Smux mpt->role = MPT_ROLE_NONE; 457107959Smux mpt_set_options(mpt); 458107959Smux if (mpt->verbose == MPT_PRT_NONE) { 459107959Smux mpt->verbose = MPT_PRT_WARN; 460107959Smux /* Print INFO level (if any) if bootverbose is set */ 461107959Smux mpt->verbose += (bootverbose != 0)? 1 : 0; 462107959Smux } 46338363Swpaul /* Make sure memory access decoders are enabled */ 46438363Swpaul cmd = pci_read_config(dev, PCIR_COMMAND, 2); 46538363Swpaul if ((cmd & PCIM_CMD_MEMEN) == 0) { 46638363Swpaul device_printf(dev, "Memory accesses disabled"); 46738363Swpaul return (ENXIO); 46838363Swpaul } 46951441Swpaul 47051441Swpaul /* 471107959Smux * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 47238363Swpaul */ 47338363Swpaul cmd |= 47438363Swpaul PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | 47538363Swpaul PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 47638363Swpaul pci_write_config(dev, PCIR_COMMAND, cmd, 2); 47738363Swpaul 478107959Smux /* 47938363Swpaul * Make sure we've disabled the ROM. 48038363Swpaul */ 48138363Swpaul data = pci_read_config(dev, PCIR_BIOS, 4); 48238363Swpaul data &= ~1; 48338363Swpaul pci_write_config(dev, PCIR_BIOS, data, 4); 48438363Swpaul 48538363Swpaul /* 48638363Swpaul * Is this part a dual? 48751441Swpaul * If so, link with our partner (around yet) 48838363Swpaul */ 48938363Swpaul if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929 || 49038363Swpaul (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC646 || 49151441Swpaul (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC7X04X || 49251441Swpaul (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_1030) { 49351441Swpaul mpt_link_peer(mpt); 49451441Swpaul } 49551441Swpaul 49638363Swpaul /* 49738363Swpaul * Set up register access. PIO mode is required for 49838363Swpaul * certain reset operations (but must be disabled for 49938363Swpaul * some cards otherwise). 50038363Swpaul */ 50138363Swpaul mpt->pci_pio_rid = PCIR_BAR(MPT_IO_BAR); 50238363Swpaul mpt->pci_pio_reg = bus_alloc_resource(dev, SYS_RES_IOPORT, 50338363Swpaul &mpt->pci_pio_rid, 0, ~0, 0, RF_ACTIVE); 50438363Swpaul if (mpt->pci_pio_reg == NULL) { 50538363Swpaul device_printf(dev, "unable to map registers in PIO mode\n"); 50638363Swpaul goto bad; 50738363Swpaul } 50838363Swpaul mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); 50938363Swpaul mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); 51038363Swpaul 51138363Swpaul /* Allocate kernel virtual memory for the 9x9's Mem0 region */ 51238363Swpaul mpt->pci_mem_rid = PCIR_BAR(MPT_MEM_BAR); 51338363Swpaul mpt->pci_reg = bus_alloc_resource(dev, SYS_RES_MEMORY, 51438363Swpaul &mpt->pci_mem_rid, 0, ~0, 0, RF_ACTIVE); 51538363Swpaul if (mpt->pci_reg == NULL) { 51638363Swpaul device_printf(dev, "Unable to memory map registers.\n"); 51738363Swpaul if (mpt->is_sas) { 51838363Swpaul device_printf(dev, "Giving Up.\n"); 51938363Swpaul goto bad; 52038363Swpaul } 52138363Swpaul device_printf(dev, "Falling back to PIO mode.\n"); 52238363Swpaul mpt->pci_st = mpt->pci_pio_st; 52351441Swpaul mpt->pci_sh = mpt->pci_pio_sh; 52451441Swpaul } else { 52538363Swpaul mpt->pci_st = rman_get_bustag(mpt->pci_reg); 52638363Swpaul mpt->pci_sh = rman_get_bushandle(mpt->pci_reg); 52738363Swpaul } 52838363Swpaul 52938363Swpaul /* Get a handle to the interrupt */ 53038363Swpaul iqd = 0; 53138363Swpaul if (mpt->msi_enable) { 53238363Swpaul /* 53338363Swpaul * First try to alloc an MSI-X message. If that 53438363Swpaul * fails, then try to alloc an MSI message instead. 53538363Swpaul */ 53638363Swpaul if (pci_msix_count(dev) == 1) { 53738363Swpaul mpt->pci_msi_count = 1; 53838363Swpaul if (pci_alloc_msix(dev, &mpt->pci_msi_count) == 0) { 53938363Swpaul iqd = 1; 54038363Swpaul } else { 54138363Swpaul mpt->pci_msi_count = 0; 54238363Swpaul } 54338363Swpaul } 54438363Swpaul if (iqd == 0 && pci_msi_count(dev) == 1) { 54538363Swpaul mpt->pci_msi_count = 1; 54638363Swpaul if (pci_alloc_msi(dev, &mpt->pci_msi_count) == 0) { 54738363Swpaul iqd = 1; 54838363Swpaul } else { 54938363Swpaul mpt->pci_msi_count = 0; 55038363Swpaul } 55138363Swpaul } 55238363Swpaul } 55338363Swpaul mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, 55438363Swpaul RF_ACTIVE | RF_SHAREABLE); 55538363Swpaul if (mpt->pci_irq == NULL) { 55638363Swpaul device_printf(dev, "could not allocate interrupt\n"); 55751441Swpaul goto bad; 55851441Swpaul } 55951441Swpaul 56038363Swpaul MPT_LOCK_SETUP(mpt); 56138363Swpaul 56238363Swpaul /* Disable interrupts at the part */ 56338363Swpaul mpt_disable_ints(mpt); 56465170Swpaul 56565170Swpaul /* Register the interrupt handler */ 56665170Swpaul if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr, 56765170Swpaul mpt, &mpt->ih)) { 56865170Swpaul device_printf(dev, "could not setup interrupt\n"); 56967233Simp goto bad; 57067233Simp } 571105675Ssilby 57265170Swpaul /* Allocate dma memory */ 573105675Ssilby/* XXX JGibbs -Should really be done based on IOCFacts. */ 574105675Ssilby if (mpt_dma_mem_alloc(mpt)) { 57538363Swpaul mpt_prt(mpt, "Could not allocate DMA memory\n"); 57638363Swpaul goto bad; 57738363Swpaul } 57845062Swpaul 57945062Swpaul /* 58048947Swpaul * Save the PCI config register values 58148947Swpaul * 58248947Swpaul * Hard resets are known to screw up the BAR for diagnostic 58350579Swpaul * memory accesses (Mem1). 58438363Swpaul * 585107959Smux * Using Mem1 is known to make the chip stop responding to 58638363Swpaul * configuration space transfers, so we need to save it now 58738363Swpaul */ 58838363Swpaul 58938363Swpaul mpt_read_config_regs(mpt); 59038363Swpaul 59138363Swpaul /* 59246514Swpaul * Disable PIO until we need it 59352244Swpaul */ 594107959Smux if (mpt->is_sas) { 59538363Swpaul pci_disable_io(dev, SYS_RES_IOPORT); 59638363Swpaul } 59765170Swpaul 59865170Swpaul /* Initialize the hardware */ 59965170Swpaul if (mpt->disabled == 0) { 60065170Swpaul MPT_LOCK(mpt); 60167087Swpaul if (mpt_attach(mpt) != 0) { 60238363Swpaul MPT_UNLOCK(mpt); 60338363Swpaul goto bad; 604105137Speter } 605105137Speter MPT_UNLOCK(mpt); 60672200Sbmilekic } else { 60772200Sbmilekic mpt_prt(mpt, "device disabled at user request\n"); 608105137Speter goto bad; 609105137Speter } 610105137Speter 611105137Speter mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown, 61267087Swpaul dev, SHUTDOWN_PRI_DEFAULT); 61338363Swpaul 61438363Swpaul if (mpt->eh == NULL) { 61538363Swpaul mpt_prt(mpt, "shutdown event registration failed\n"); 61638363Swpaul MPT_LOCK(mpt); 61738363Swpaul (void) mpt_detach(mpt); 61838363Swpaul MPT_UNLOCK(mpt); 61938363Swpaul goto bad; 62038363Swpaul } 62138363Swpaul KASSERT(MPT_OWNED(mpt) == 0, ("leaving attach with device locked")); 62238363Swpaul return (0); 62338363Swpaul 62438363Swpaulbad: 62538363Swpaul mpt_dma_mem_free(mpt); 62638363Swpaul mpt_free_bus_resources(mpt); 62738363Swpaul mpt_unlink_peer(mpt); 62838363Swpaul 62938363Swpaul MPT_LOCK_DESTROY(mpt); 63038363Swpaul 63138363Swpaul /* 63238363Swpaul * but return zero to preserve unit numbering 63338363Swpaul */ 63438363Swpaul return (0); 63538363Swpaul} 63638363Swpaul 63738363Swpaul/* 63838363Swpaul * Free bus resources 63945062Swpaul */ 64038363Swpaulstatic void 64145062Swpaulmpt_free_bus_resources(struct mpt_softc *mpt) 64238363Swpaul{ 64345062Swpaul if (mpt->ih) { 64438363Swpaul bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih); 64545062Swpaul mpt->ih = 0; 64645062Swpaul } 64745062Swpaul 64845062Swpaul if (mpt->pci_irq) { 64945062Swpaul bus_release_resource(mpt->dev, SYS_RES_IRQ, 65045062Swpaul mpt->pci_msi_count ? 1 : 0, mpt->pci_irq); 65138363Swpaul mpt->pci_irq = 0; 65238363Swpaul } 65338363Swpaul 65438363Swpaul if (mpt->pci_msi_count) { 65538363Swpaul pci_release_msi(mpt->dev); 65638363Swpaul mpt->pci_msi_count = 0; 65738363Swpaul } 65838363Swpaul 65938363Swpaul if (mpt->pci_pio_reg) { 66038363Swpaul bus_release_resource(mpt->dev, SYS_RES_IOPORT, mpt->pci_pio_rid, 66138363Swpaul mpt->pci_pio_reg); 66238363Swpaul mpt->pci_pio_reg = 0; 66338363Swpaul } 66438363Swpaul if (mpt->pci_reg) { 66538363Swpaul bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_rid, 66638363Swpaul mpt->pci_reg); 66738363Swpaul mpt->pci_reg = 0; 66838363Swpaul } 66938363Swpaul MPT_LOCK_DESTROY(mpt); 67046204Swpaul} 67146204Swpaul 67246204Swpaul 67345693Swpaul/* 67446204Swpaul * Disconnect ourselves from the system. 67538363Swpaul */ 67645601Swpaulstatic int 67740097Swpaulmpt_pci_detach(device_t dev) 67847627Swpaul{ 67946204Swpaul struct mpt_softc *mpt; 68051301Swpaul 68145629Swpaul mpt = (struct mpt_softc*)device_get_softc(dev); 68254697Swpaul 683108752Ssilby if (mpt) { 68465170Swpaul MPT_LOCK(mpt); 68565170Swpaul mpt_disable_ints(mpt); 68668227Ssanpei mpt_detach(mpt); 68767233Simp mpt_reset(mpt, /*reinit*/FALSE); 68867233Simp mpt_dma_mem_free(mpt); 68982446Swpaul mpt_free_bus_resources(mpt); 69082446Swpaul mpt_raid_free_mem(mpt); 69182446Swpaul if (mpt->eh != NULL) { 69238363Swpaul EVENTHANDLER_DEREGISTER(shutdown_final, mpt->eh); 69338363Swpaul } 69438363Swpaul MPT_UNLOCK(mpt); 69538363Swpaul } 69638363Swpaul return(0); 69738363Swpaul} 69838363Swpaul 69938363Swpaul 70038363Swpaul/* 70138363Swpaul * Disable the hardware 70238363Swpaul */ 70338363Swpaulstatic int 70438363Swpaulmpt_pci_shutdown(device_t dev) 70538363Swpaul{ 70638363Swpaul struct mpt_softc *mpt; 70738363Swpaul 70865170Swpaul mpt = (struct mpt_softc *)device_get_softc(dev); 70938363Swpaul if (mpt) { 71038363Swpaul int r; 71138363Swpaul MPT_LOCK(mpt); 71238363Swpaul r = mpt_shutdown(mpt); 71338363Swpaul MPT_UNLOCK(mpt); 71438363Swpaul return (r); 71538363Swpaul } 71638363Swpaul return(0); 71738363Swpaul} 71838363Swpaul 71938363Swpaulstatic int 72038363Swpaulmpt_dma_mem_alloc(struct mpt_softc *mpt) 72138363Swpaul{ 72238363Swpaul int i, error, nsegs; 72338363Swpaul uint8_t *vptr; 72438363Swpaul uint32_t pptr, end; 72538363Swpaul size_t len; 72638363Swpaul struct mpt_map_info mi; 72738363Swpaul 72838363Swpaul /* Check if we alreay have allocated the reply memory */ 72938363Swpaul if (mpt->reply_phys != 0) { 73038363Swpaul return 0; 73146204Swpaul } 73246204Swpaul 73346204Swpaul len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt); 734#ifdef RELENG_4 735 mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK); 736 if (mpt->request_pool == NULL) { 737 mpt_prt(mpt, "cannot allocate request pool\n"); 738 return (1); 739 } 740 memset(mpt->request_pool, 0, len); 741#else 742 mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 743 if (mpt->request_pool == NULL) { 744 mpt_prt(mpt, "cannot allocate request pool\n"); 745 return (1); 746 } 747#endif 748 749 /* 750 * Create a parent dma tag for this device. 751 * 752 * Align at byte boundaries, 753 * Limit to 32-bit addressing for request/reply queues. 754 */ 755 if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev), 756 /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, 757 /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, 758 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 759 /*nsegments*/BUS_SPACE_MAXSIZE_32BIT, 760 /*maxsegsz*/BUS_SPACE_UNRESTRICTED, /*flags*/0, 761 &mpt->parent_dmat) != 0) { 762 mpt_prt(mpt, "cannot create parent dma tag\n"); 763 return (1); 764 } 765 766 /* Create a child tag for reply buffers */ 767 if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 768 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 769 NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0, 770 &mpt->reply_dmat) != 0) { 771 mpt_prt(mpt, "cannot create a dma tag for replies\n"); 772 return (1); 773 } 774 775 /* Allocate some DMA accessable memory for replies */ 776 if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply, 777 BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) { 778 mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n", 779 (u_long) (2 * PAGE_SIZE)); 780 return (1); 781 } 782 783 mi.mpt = mpt; 784 mi.error = 0; 785 786 /* Load and lock it into "bus space" */ 787 bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply, 788 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0); 789 790 if (mi.error) { 791 mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n", 792 mi.error); 793 return (1); 794 } 795 mpt->reply_phys = mi.phys; 796 797 /* Create a child tag for data buffers */ 798 799 /* 800 * XXX: we should say that nsegs is 'unrestricted, but that 801 * XXX: tickles a horrible bug in the busdma code. Instead, 802 * XXX: we'll derive a reasonable segment limit from MAXPHYS 803 */ 804 nsegs = (MAXPHYS / PAGE_SIZE) + 1; 805 if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 806 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 807 NULL, NULL, MAXBSIZE, nsegs, BUS_SPACE_MAXSIZE_32BIT, 0, 808 &mpt->buffer_dmat) != 0) { 809 mpt_prt(mpt, "cannot create a dma tag for data buffers\n"); 810 return (1); 811 } 812 813 /* Create a child tag for request buffers */ 814 if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 815 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 816 NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0, 817 &mpt->request_dmat) != 0) { 818 mpt_prt(mpt, "cannot create a dma tag for requests\n"); 819 return (1); 820 } 821 822 /* Allocate some DMA accessable memory for requests */ 823 if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request, 824 BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) { 825 mpt_prt(mpt, "cannot allocate %d bytes of request memory\n", 826 MPT_REQ_MEM_SIZE(mpt)); 827 return (1); 828 } 829 830 mi.mpt = mpt; 831 mi.error = 0; 832 833 /* Load and lock it into "bus space" */ 834 bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request, 835 MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0); 836 837 if (mi.error) { 838 mpt_prt(mpt, "error %d loading dma map for DMA request queue\n", 839 mi.error); 840 return (1); 841 } 842 mpt->request_phys = mi.phys; 843 844 /* 845 * Now create per-request dma maps 846 */ 847 i = 0; 848 pptr = mpt->request_phys; 849 vptr = mpt->request; 850 end = pptr + MPT_REQ_MEM_SIZE(mpt); 851 while(pptr < end) { 852 request_t *req = &mpt->request_pool[i]; 853 req->index = i++; 854 855 /* Store location of Request Data */ 856 req->req_pbuf = pptr; 857 req->req_vbuf = vptr; 858 859 pptr += MPT_REQUEST_AREA; 860 vptr += MPT_REQUEST_AREA; 861 862 req->sense_pbuf = (pptr - MPT_SENSE_SIZE); 863 req->sense_vbuf = (vptr - MPT_SENSE_SIZE); 864 865 error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap); 866 if (error) { 867 mpt_prt(mpt, "error %d creating per-cmd DMA maps\n", 868 error); 869 return (1); 870 } 871 } 872 873 return (0); 874} 875 876 877 878/* Deallocate memory that was allocated by mpt_dma_mem_alloc 879 */ 880static void 881mpt_dma_mem_free(struct mpt_softc *mpt) 882{ 883 int i; 884 885 /* Make sure we aren't double destroying */ 886 if (mpt->reply_dmat == 0) { 887 mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n"); 888 return; 889 } 890 891 for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) { 892 bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap); 893 } 894 bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap); 895 bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap); 896 bus_dma_tag_destroy(mpt->request_dmat); 897 bus_dma_tag_destroy(mpt->buffer_dmat); 898 bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap); 899 bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap); 900 bus_dma_tag_destroy(mpt->reply_dmat); 901 bus_dma_tag_destroy(mpt->parent_dmat); 902 mpt->reply_dmat = 0; 903 free(mpt->request_pool, M_DEVBUF); 904 mpt->request_pool = 0; 905 906} 907 908 909 910/* Reads modifiable (via PCI transactions) config registers */ 911static void 912mpt_read_config_regs(struct mpt_softc *mpt) 913{ 914 mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2); 915 mpt->pci_cfg.LatencyTimer_LineSize = 916 pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2); 917 mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4); 918 mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4); 919 mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4); 920 mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4); 921 mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4); 922 mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4); 923 mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1); 924 mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4); 925} 926 927/* Sets modifiable config registers */ 928void 929mpt_set_config_regs(struct mpt_softc *mpt) 930{ 931 uint32_t val; 932 933#define MPT_CHECK(reg, offset, size) \ 934 val = pci_read_config(mpt->dev, offset, size); \ 935 if (mpt->pci_cfg.reg != val) { \ 936 mpt_prt(mpt, \ 937 "Restoring " #reg " to 0x%X from 0x%X\n", \ 938 mpt->pci_cfg.reg, val); \ 939 } 940 941 if (mpt->verbose >= MPT_PRT_DEBUG) { 942 MPT_CHECK(Command, PCIR_COMMAND, 2); 943 MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2); 944 MPT_CHECK(IO_BAR, PCIR_BAR(0), 4); 945 MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4); 946 MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4); 947 MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4); 948 MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4); 949 MPT_CHECK(ROM_BAR, PCIR_BIOS, 4); 950 MPT_CHECK(IntLine, PCIR_INTLINE, 1); 951 MPT_CHECK(PMCSR, 0x44, 4); 952 } 953#undef MPT_CHECK 954 955 pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2); 956 pci_write_config(mpt->dev, PCIR_CACHELNSZ, 957 mpt->pci_cfg.LatencyTimer_LineSize, 2); 958 pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4); 959 pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4); 960 pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4); 961 pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4); 962 pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4); 963 pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4); 964 pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1); 965 pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4); 966} 967 968static void 969mpt_pci_intr(void *arg) 970{ 971 struct mpt_softc *mpt; 972 973 mpt = (struct mpt_softc *)arg; 974 MPT_LOCK(mpt); 975 mpt_intr(mpt); 976 MPT_UNLOCK(mpt); 977} 978