mpt_pci.c revision 180152
1119418Sobrien/*- 2102596Smjacob * PCI specific probe and attach routines for LSI Fusion Adapters 3101704Smjacob * FreeBSD Version. 4101704Smjacob * 5119418Sobrien * Copyright (c) 2000, 2001 by Greg Ansley 6101704Smjacob * Partially derived from Matt Jacob's ISP driver. 7119418Sobrien * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002 by Matthew Jacob 8119418Sobrien * Feral Software 9119418Sobrien * All rights reserved. 10101704Smjacob * 11101704Smjacob * Redistribution and use in source and binary forms, with or without 12101704Smjacob * modification, are permitted provided that the following conditions 13101704Smjacob * are met: 14101704Smjacob * 1. Redistributions of source code must retain the above copyright 15101704Smjacob * notice immediately at the beginning of the file, without modification, 16101704Smjacob * this list of conditions, and the following disclaimer. 17101704Smjacob * 2. The name of the author may not be used to endorse or promote products 18101704Smjacob * derived from this software without specific prior written permission. 19101704Smjacob * 20101704Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21101704Smjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22101704Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23101704Smjacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24101704Smjacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25101704Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26101704Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27101704Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28101704Smjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29101704Smjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30101704Smjacob * SUCH DAMAGE. 31101704Smjacob */ 32156000Smjacob/*- 33156000Smjacob * Copyright (c) 2002, 2006 by Matthew Jacob 34156000Smjacob * All rights reserved. 35156000Smjacob * 36156000Smjacob * Redistribution and use in source and binary forms, with or without 37156000Smjacob * modification, are permitted provided that the following conditions are 38156000Smjacob * met: 39156000Smjacob * 1. Redistributions of source code must retain the above copyright 40156000Smjacob * notice, this list of conditions and the following disclaimer. 41156000Smjacob * 2. Redistributions in binary form must reproduce at minimum a disclaimer 42156000Smjacob * substantially similar to the "NO WARRANTY" disclaimer below 43156000Smjacob * ("Disclaimer") and any redistribution must be conditioned upon including 44156000Smjacob * a substantially similar Disclaimer requirement for further binary 45156000Smjacob * redistribution. 46156000Smjacob * 3. Neither the names of the above listed copyright holders nor the names 47156000Smjacob * of any contributors may be used to endorse or promote products derived 48156000Smjacob * from this software without specific prior written permission. 49156000Smjacob * 50156000Smjacob * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 51156000Smjacob * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52156000Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53156000Smjacob * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 54156000Smjacob * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55156000Smjacob * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56156000Smjacob * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57156000Smjacob * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58156000Smjacob * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59156000Smjacob * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 60156000Smjacob * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61156000Smjacob * 62156000Smjacob * Support from Chris Ellsworth in order to make SAS adapters work 63156000Smjacob * is gratefully acknowledged. 64159052Smjacob * 65159052Smjacob * Support from LSI-Logic has also gone a great deal toward making this a 66159052Smjacob * workable subsystem and is gratefully acknowledged. 67156000Smjacob */ 68147883Sscottl/* 69147883Sscottl * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 70147883Sscottl * Copyright (c) 2005, WHEEL Sp. z o.o. 71147883Sscottl * Copyright (c) 2004, 2005 Justin T. Gibbs 72147883Sscottl * All rights reserved. 73147883Sscottl * 74147883Sscottl * Redistribution and use in source and binary forms, with or without 75147883Sscottl * modification, are permitted provided that the following conditions are 76147883Sscottl * met: 77147883Sscottl * 1. Redistributions of source code must retain the above copyright 78147883Sscottl * notice, this list of conditions and the following disclaimer. 79147883Sscottl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 80147883Sscottl * substantially similar to the "NO WARRANTY" disclaimer below 81147883Sscottl * ("Disclaimer") and any redistribution must be conditioned upon including 82147883Sscottl * a substantially similar Disclaimer requirement for further binary 83147883Sscottl * redistribution. 84148679Sgibbs * 3. Neither the names of the above listed copyright holders nor the names 85148679Sgibbs * of any contributors may be used to endorse or promote products derived 86148679Sgibbs * from this software without specific prior written permission. 87147883Sscottl * 88147883Sscottl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 89147883Sscottl * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 90147883Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 91147883Sscottl * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 92147883Sscottl * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 93147883Sscottl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 94147883Sscottl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 95147883Sscottl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 96147883Sscottl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 97147883Sscottl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 98147883Sscottl * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 99147883Sscottl */ 100101704Smjacob 101119418Sobrien#include <sys/cdefs.h> 102119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/mpt/mpt_pci.c 180152 2008-07-01 19:44:38Z jhb $"); 103119418Sobrien 104147883Sscottl#include <dev/mpt/mpt.h> 105147883Sscottl#include <dev/mpt/mpt_cam.h> 106147883Sscottl#include <dev/mpt/mpt_raid.h> 107102199Smjacob 108165814Smjacob#if __FreeBSD_version < 700000 109166721Sjhb#define pci_msix_count(x) 0 110165814Smjacob#define pci_msi_count(x) 0 111165814Smjacob#define pci_alloc_msi(x, y) 1 112166721Sjhb#define pci_alloc_msix(x, y) 1 113165814Smjacob#define pci_release_msi(x) do { ; } while (0) 114165814Smjacob#endif 115101704Smjacob 116101704Smjacob#ifndef PCI_VENDOR_LSI 117101704Smjacob#define PCI_VENDOR_LSI 0x1000 118101704Smjacob#endif 119101704Smjacob 120101704Smjacob#ifndef PCI_PRODUCT_LSI_FC909 121101704Smjacob#define PCI_PRODUCT_LSI_FC909 0x0620 122101704Smjacob#endif 123101704Smjacob 124102596Smjacob#ifndef PCI_PRODUCT_LSI_FC909A 125102596Smjacob#define PCI_PRODUCT_LSI_FC909A 0x0621 126102596Smjacob#endif 127102596Smjacob 128103829Smjacob#ifndef PCI_PRODUCT_LSI_FC919 129103829Smjacob#define PCI_PRODUCT_LSI_FC919 0x0624 130103829Smjacob#endif 131103829Smjacob 132101704Smjacob#ifndef PCI_PRODUCT_LSI_FC929 133101704Smjacob#define PCI_PRODUCT_LSI_FC929 0x0622 134101704Smjacob#endif 135101704Smjacob 136150007Smjacob#ifndef PCI_PRODUCT_LSI_FC929X 137150007Smjacob#define PCI_PRODUCT_LSI_FC929X 0x0626 138150007Smjacob#endif 139150007Smjacob 140159494Smjacob#ifndef PCI_PRODUCT_LSI_FC919X 141159494Smjacob#define PCI_PRODUCT_LSI_FC919X 0x0628 142159494Smjacob#endif 143159494Smjacob 144158279Smjacob#ifndef PCI_PRODUCT_LSI_FC7X04X 145158279Smjacob#define PCI_PRODUCT_LSI_FC7X04X 0x0640 146158279Smjacob#endif 147158279Smjacob 148162140Smjacob#ifndef PCI_PRODUCT_LSI_FC646 149162140Smjacob#define PCI_PRODUCT_LSI_FC646 0x0646 150162140Smjacob#endif 151162140Smjacob 152101704Smjacob#ifndef PCI_PRODUCT_LSI_1030 153101704Smjacob#define PCI_PRODUCT_LSI_1030 0x0030 154101704Smjacob#endif 155101704Smjacob 156155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064 157155521Smjacob#define PCI_PRODUCT_LSI_SAS1064 0x0050 158155521Smjacob#endif 159155521Smjacob 160155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064A 161155521Smjacob#define PCI_PRODUCT_LSI_SAS1064A 0x005C 162155521Smjacob#endif 163155521Smjacob 164155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064E 165155521Smjacob#define PCI_PRODUCT_LSI_SAS1064E 0x0056 166155521Smjacob#endif 167155521Smjacob 168155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1066 169155521Smjacob#define PCI_PRODUCT_LSI_SAS1066 0x005E 170155521Smjacob#endif 171155521Smjacob 172155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1066E 173155521Smjacob#define PCI_PRODUCT_LSI_SAS1066E 0x005A 174155521Smjacob#endif 175155521Smjacob 176155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1068 177155521Smjacob#define PCI_PRODUCT_LSI_SAS1068 0x0054 178155521Smjacob#endif 179155521Smjacob 180155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1068E 181155521Smjacob#define PCI_PRODUCT_LSI_SAS1068E 0x0058 182155521Smjacob#endif 183155521Smjacob 184155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1078 185172219Sambrisko#define PCI_PRODUCT_LSI_SAS1078 0x0062 186155521Smjacob#endif 187155521Smjacob 188178896Sdelphij#ifndef PCI_PRODUCT_LSI_SAS1078DE 189178896Sdelphij#define PCI_PRODUCT_LSI_SAS1078DE 0x007C 190178896Sdelphij#endif 191178896Sdelphij 192102303Smjacob#ifndef PCIM_CMD_SERRESPEN 193102303Smjacob#define PCIM_CMD_SERRESPEN 0x0100 194102303Smjacob#endif 195101704Smjacob 196101704Smjacob 197147883Sscottl#define MPT_IO_BAR 0 198147883Sscottl#define MPT_MEM_BAR 1 199101704Smjacob 200147883Sscottlstatic int mpt_pci_probe(device_t); 201147883Sscottlstatic int mpt_pci_attach(device_t); 202147883Sscottlstatic void mpt_free_bus_resources(struct mpt_softc *mpt); 203147883Sscottlstatic int mpt_pci_detach(device_t); 204147883Sscottlstatic int mpt_pci_shutdown(device_t); 205147883Sscottlstatic int mpt_dma_mem_alloc(struct mpt_softc *mpt); 206147883Sscottlstatic void mpt_dma_mem_free(struct mpt_softc *mpt); 207147883Sscottlstatic void mpt_read_config_regs(struct mpt_softc *mpt); 208102199Smjacobstatic void mpt_pci_intr(void *); 209101704Smjacob 210101704Smjacobstatic device_method_t mpt_methods[] = { 211101704Smjacob /* Device interface */ 212147883Sscottl DEVMETHOD(device_probe, mpt_pci_probe), 213147883Sscottl DEVMETHOD(device_attach, mpt_pci_attach), 214147883Sscottl DEVMETHOD(device_detach, mpt_pci_detach), 215147883Sscottl DEVMETHOD(device_shutdown, mpt_pci_shutdown), 216101704Smjacob { 0, 0 } 217101704Smjacob}; 218101704Smjacob 219101704Smjacobstatic driver_t mpt_driver = { 220147883Sscottl "mpt", mpt_methods, sizeof(struct mpt_softc) 221101704Smjacob}; 222101704Smjacobstatic devclass_t mpt_devclass; 223101704SmjacobDRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0); 224165058SmjacobMODULE_DEPEND(mpt, pci, 1, 1, 1); 225101704SmjacobMODULE_VERSION(mpt, 1); 226101704Smjacob 227101704Smjacobstatic int 228147883Sscottlmpt_pci_probe(device_t dev) 229101704Smjacob{ 230101704Smjacob char *desc; 231101704Smjacob 232160290Smjacob if (pci_get_vendor(dev) != PCI_VENDOR_LSI) { 233101704Smjacob return (ENXIO); 234160290Smjacob } 235101704Smjacob 236101704Smjacob switch ((pci_get_device(dev) & ~1)) { 237101704Smjacob case PCI_PRODUCT_LSI_FC909: 238101704Smjacob desc = "LSILogic FC909 FC Adapter"; 239101704Smjacob break; 240102596Smjacob case PCI_PRODUCT_LSI_FC909A: 241102596Smjacob desc = "LSILogic FC909A FC Adapter"; 242102596Smjacob break; 243103829Smjacob case PCI_PRODUCT_LSI_FC919: 244103829Smjacob desc = "LSILogic FC919 FC Adapter"; 245103829Smjacob break; 246101704Smjacob case PCI_PRODUCT_LSI_FC929: 247162140Smjacob desc = "Dual LSILogic FC929 FC Adapter"; 248101704Smjacob break; 249159494Smjacob case PCI_PRODUCT_LSI_FC919X: 250162140Smjacob desc = "LSILogic FC919 FC PCI-X Adapter"; 251159494Smjacob break; 252150007Smjacob case PCI_PRODUCT_LSI_FC929X: 253162140Smjacob desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter"; 254150007Smjacob break; 255162140Smjacob case PCI_PRODUCT_LSI_FC646: 256162140Smjacob desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter"; 257162140Smjacob break; 258158279Smjacob case PCI_PRODUCT_LSI_FC7X04X: 259162140Smjacob desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter"; 260158279Smjacob break; 261101704Smjacob case PCI_PRODUCT_LSI_1030: 262101704Smjacob desc = "LSILogic 1030 Ultra4 Adapter"; 263101704Smjacob break; 264155521Smjacob case PCI_PRODUCT_LSI_SAS1064: 265155521Smjacob case PCI_PRODUCT_LSI_SAS1064A: 266155521Smjacob case PCI_PRODUCT_LSI_SAS1064E: 267155521Smjacob case PCI_PRODUCT_LSI_SAS1066: 268155521Smjacob case PCI_PRODUCT_LSI_SAS1066E: 269155521Smjacob case PCI_PRODUCT_LSI_SAS1068: 270155521Smjacob case PCI_PRODUCT_LSI_SAS1068E: 271155521Smjacob case PCI_PRODUCT_LSI_SAS1078: 272178896Sdelphij case PCI_PRODUCT_LSI_SAS1078DE: 273162140Smjacob desc = "LSILogic SAS/SATA Adapter"; 274155521Smjacob break; 275101704Smjacob default: 276101704Smjacob return (ENXIO); 277101704Smjacob } 278101704Smjacob 279101704Smjacob device_set_desc(dev, desc); 280147883Sscottl return (0); 281101704Smjacob} 282101704Smjacob 283157117Smjacob#if __FreeBSD_version < 500000 284101704Smjacobstatic void 285147883Sscottlmpt_set_options(struct mpt_softc *mpt) 286101704Smjacob{ 287101704Smjacob int bitmap; 288101704Smjacob 289101704Smjacob bitmap = 0; 290101704Smjacob if (getenv_int("mpt_disable", &bitmap)) { 291101704Smjacob if (bitmap & (1 << mpt->unit)) { 292101704Smjacob mpt->disabled = 1; 293101704Smjacob } 294101704Smjacob } 295101704Smjacob bitmap = 0; 296101704Smjacob if (getenv_int("mpt_debug", &bitmap)) { 297101704Smjacob if (bitmap & (1 << mpt->unit)) { 298147883Sscottl mpt->verbose = MPT_PRT_DEBUG; 299101704Smjacob } 300101704Smjacob } 301157117Smjacob bitmap = 0; 302157662Smjacob if (getenv_int("mpt_debug1", &bitmap)) { 303157117Smjacob if (bitmap & (1 << mpt->unit)) { 304157662Smjacob mpt->verbose = MPT_PRT_DEBUG1; 305157117Smjacob } 306157117Smjacob } 307157117Smjacob bitmap = 0; 308157662Smjacob if (getenv_int("mpt_debug2", &bitmap)) { 309157117Smjacob if (bitmap & (1 << mpt->unit)) { 310157662Smjacob mpt->verbose = MPT_PRT_DEBUG2; 311157117Smjacob } 312157117Smjacob } 313157117Smjacob bitmap = 0; 314157662Smjacob if (getenv_int("mpt_debug3", &bitmap)) { 315157117Smjacob if (bitmap & (1 << mpt->unit)) { 316157662Smjacob mpt->verbose = MPT_PRT_DEBUG3; 317157117Smjacob } 318157117Smjacob } 319160290Smjacob 320160290Smjacob mpt->cfg_role = MPT_ROLE_DEFAULT; 321160290Smjacob bitmap = 0; 322160290Smjacob if (getenv_int("mpt_nil_role", &bitmap)) { 323160290Smjacob if (bitmap & (1 << mpt->unit)) { 324160290Smjacob mpt->cfg_role = 0; 325160290Smjacob } 326160290Smjacob mpt->do_cfg_role = 1; 327160290Smjacob } 328160290Smjacob bitmap = 0; 329160290Smjacob if (getenv_int("mpt_tgt_role", &bitmap)) { 330160290Smjacob if (bitmap & (1 << mpt->unit)) { 331160290Smjacob mpt->cfg_role |= MPT_ROLE_TARGET; 332160290Smjacob } 333160290Smjacob mpt->do_cfg_role = 1; 334160290Smjacob } 335160290Smjacob bitmap = 0; 336160290Smjacob if (getenv_int("mpt_ini_role", &bitmap)) { 337160290Smjacob if (bitmap & (1 << mpt->unit)) { 338160290Smjacob mpt->cfg_role |= MPT_ROLE_INITIATOR; 339160290Smjacob } 340160290Smjacob mpt->do_cfg_role = 1; 341160290Smjacob } 342164416Smjacob mpt->msi_enable = 0; 343101704Smjacob} 344101704Smjacob#else 345101704Smjacobstatic void 346147883Sscottlmpt_set_options(struct mpt_softc *mpt) 347101704Smjacob{ 348101704Smjacob int tval; 349101704Smjacob 350101704Smjacob tval = 0; 351101704Smjacob if (resource_int_value(device_get_name(mpt->dev), 352101704Smjacob device_get_unit(mpt->dev), "disable", &tval) == 0 && tval != 0) { 353101704Smjacob mpt->disabled = 1; 354101704Smjacob } 355101704Smjacob tval = 0; 356101704Smjacob if (resource_int_value(device_get_name(mpt->dev), 357101704Smjacob device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { 358159041Smjacob mpt->verbose = tval; 359101704Smjacob } 360160290Smjacob tval = -1; 361157117Smjacob if (resource_int_value(device_get_name(mpt->dev), 362160290Smjacob device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && 363157117Smjacob tval <= 3) { 364160290Smjacob mpt->cfg_role = tval; 365160290Smjacob mpt->do_cfg_role = 1; 366157117Smjacob } 367164416Smjacob 368164416Smjacob tval = 0; 369164417Smjacob mpt->msi_enable = 0; 370164416Smjacob if (resource_int_value(device_get_name(mpt->dev), 371164416Smjacob device_get_unit(mpt->dev), "msi_enable", &tval) == 0 && tval == 1) { 372164416Smjacob mpt->msi_enable = 1; 373164416Smjacob } 374101704Smjacob} 375101704Smjacob#endif 376101704Smjacob 377101704Smjacob 378102303Smjacobstatic void 379147883Sscottlmpt_link_peer(struct mpt_softc *mpt) 380102303Smjacob{ 381147883Sscottl struct mpt_softc *mpt2; 382102303Smjacob 383157662Smjacob if (mpt->unit == 0) { 384102303Smjacob return; 385157662Smjacob } 386102303Smjacob /* 387102303Smjacob * XXX: depends on probe order 388102303Smjacob */ 389147883Sscottl mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1); 390102303Smjacob 391102303Smjacob if (mpt2 == NULL) { 392102303Smjacob return; 393102303Smjacob } 394102303Smjacob if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) { 395102303Smjacob return; 396102303Smjacob } 397102303Smjacob if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) { 398102303Smjacob return; 399102303Smjacob } 400102303Smjacob mpt->mpt2 = mpt2; 401102303Smjacob mpt2->mpt2 = mpt; 402147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 403147883Sscottl mpt_prt(mpt, "linking with peer (mpt%d)\n", 404102303Smjacob device_get_unit(mpt2->dev)); 405102303Smjacob } 406102303Smjacob} 407102303Smjacob 408157662Smjacobstatic void 409157662Smjacobmpt_unlink_peer(struct mpt_softc *mpt) 410157662Smjacob{ 411157662Smjacob if (mpt->mpt2) { 412157662Smjacob mpt->mpt2->mpt2 = NULL; 413157662Smjacob } 414157662Smjacob} 415102303Smjacob 416157662Smjacob 417101704Smjacobstatic int 418147883Sscottlmpt_pci_attach(device_t dev) 419101704Smjacob{ 420147883Sscottl struct mpt_softc *mpt; 421147883Sscottl int iqd; 422147883Sscottl uint32_t data, cmd; 423101704Smjacob 424101704Smjacob /* Allocate the softc structure */ 425147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 426101704Smjacob if (mpt == NULL) { 427101704Smjacob device_printf(dev, "cannot allocate softc\n"); 428101704Smjacob return (ENOMEM); 429101704Smjacob } 430157354Smjacob memset(mpt, 0, sizeof(struct mpt_softc)); 431101704Smjacob switch ((pci_get_device(dev) & ~1)) { 432101704Smjacob case PCI_PRODUCT_LSI_FC909: 433102596Smjacob case PCI_PRODUCT_LSI_FC909A: 434103829Smjacob case PCI_PRODUCT_LSI_FC919: 435101704Smjacob case PCI_PRODUCT_LSI_FC929: 436159494Smjacob case PCI_PRODUCT_LSI_FC919X: 437162140Smjacob case PCI_PRODUCT_LSI_FC646: 438158279Smjacob case PCI_PRODUCT_LSI_FC7X04X: 439101704Smjacob mpt->is_fc = 1; 440101704Smjacob break; 441155521Smjacob case PCI_PRODUCT_LSI_SAS1064: 442155521Smjacob case PCI_PRODUCT_LSI_SAS1064A: 443155521Smjacob case PCI_PRODUCT_LSI_SAS1064E: 444155521Smjacob case PCI_PRODUCT_LSI_SAS1066: 445155521Smjacob case PCI_PRODUCT_LSI_SAS1066E: 446155521Smjacob case PCI_PRODUCT_LSI_SAS1068: 447155521Smjacob case PCI_PRODUCT_LSI_SAS1068E: 448155521Smjacob case PCI_PRODUCT_LSI_SAS1078: 449178896Sdelphij case PCI_PRODUCT_LSI_SAS1078DE: 450155521Smjacob mpt->is_sas = 1; 451155521Smjacob break; 452101704Smjacob default: 453159178Smjacob mpt->is_spi = 1; 454101704Smjacob break; 455101704Smjacob } 456101704Smjacob mpt->dev = dev; 457101704Smjacob mpt->unit = device_get_unit(dev); 458147883Sscottl mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT; 459147883Sscottl mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; 460147883Sscottl mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; 461155521Smjacob mpt->verbose = MPT_PRT_NONE; 462157662Smjacob mpt->role = MPT_ROLE_NONE; 463101704Smjacob mpt_set_options(mpt); 464155521Smjacob if (mpt->verbose == MPT_PRT_NONE) { 465155521Smjacob mpt->verbose = MPT_PRT_WARN; 466155521Smjacob /* Print INFO level (if any) if bootverbose is set */ 467155521Smjacob mpt->verbose += (bootverbose != 0)? 1 : 0; 468155521Smjacob } 469101704Smjacob /* Make sure memory access decoders are enabled */ 470101704Smjacob cmd = pci_read_config(dev, PCIR_COMMAND, 2); 471101704Smjacob if ((cmd & PCIM_CMD_MEMEN) == 0) { 472101704Smjacob device_printf(dev, "Memory accesses disabled"); 473157662Smjacob return (ENXIO); 474101704Smjacob } 475101704Smjacob 476101704Smjacob /* 477101704Smjacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 478101704Smjacob */ 479101704Smjacob cmd |= 480101704Smjacob PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | 481101704Smjacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 482101704Smjacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 483101704Smjacob 484101704Smjacob /* 485101704Smjacob * Make sure we've disabled the ROM. 486101704Smjacob */ 487101704Smjacob data = pci_read_config(dev, PCIR_BIOS, 4); 488101704Smjacob data &= ~1; 489101704Smjacob pci_write_config(dev, PCIR_BIOS, data, 4); 490101704Smjacob 491102303Smjacob /* 492102303Smjacob * Is this part a dual? 493102303Smjacob * If so, link with our partner (around yet) 494102303Smjacob */ 495102303Smjacob if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929 || 496162140Smjacob (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC646 || 497158279Smjacob (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC7X04X || 498102303Smjacob (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_1030) { 499102303Smjacob mpt_link_peer(mpt); 500101704Smjacob } 501101704Smjacob 502147883Sscottl /* 503147883Sscottl * Set up register access. PIO mode is required for 504155521Smjacob * certain reset operations (but must be disabled for 505155521Smjacob * some cards otherwise). 506147883Sscottl */ 507147883Sscottl mpt->pci_pio_rid = PCIR_BAR(MPT_IO_BAR); 508147883Sscottl mpt->pci_pio_reg = bus_alloc_resource(dev, SYS_RES_IOPORT, 509147883Sscottl &mpt->pci_pio_rid, 0, ~0, 0, RF_ACTIVE); 510147883Sscottl if (mpt->pci_pio_reg == NULL) { 511147883Sscottl device_printf(dev, "unable to map registers in PIO mode\n"); 512147883Sscottl goto bad; 513147883Sscottl } 514147883Sscottl mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); 515147883Sscottl mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); 516147883Sscottl 517101704Smjacob /* Allocate kernel virtual memory for the 9x9's Mem0 region */ 518147883Sscottl mpt->pci_mem_rid = PCIR_BAR(MPT_MEM_BAR); 519101704Smjacob mpt->pci_reg = bus_alloc_resource(dev, SYS_RES_MEMORY, 520147883Sscottl &mpt->pci_mem_rid, 0, ~0, 0, RF_ACTIVE); 521101704Smjacob if (mpt->pci_reg == NULL) { 522147883Sscottl device_printf(dev, "Unable to memory map registers.\n"); 523155521Smjacob if (mpt->is_sas) { 524155521Smjacob device_printf(dev, "Giving Up.\n"); 525155521Smjacob goto bad; 526155521Smjacob } 527147883Sscottl device_printf(dev, "Falling back to PIO mode.\n"); 528147883Sscottl mpt->pci_st = mpt->pci_pio_st; 529147883Sscottl mpt->pci_sh = mpt->pci_pio_sh; 530147883Sscottl } else { 531147883Sscottl mpt->pci_st = rman_get_bustag(mpt->pci_reg); 532147883Sscottl mpt->pci_sh = rman_get_bushandle(mpt->pci_reg); 533101704Smjacob } 534101704Smjacob 535101704Smjacob /* Get a handle to the interrupt */ 536101704Smjacob iqd = 0; 537166721Sjhb if (mpt->msi_enable) { 538166721Sjhb /* 539166721Sjhb * First try to alloc an MSI-X message. If that 540166721Sjhb * fails, then try to alloc an MSI message instead. 541166721Sjhb */ 542166721Sjhb if (pci_msix_count(dev) == 1) { 543166721Sjhb mpt->pci_msi_count = 1; 544166721Sjhb if (pci_alloc_msix(dev, &mpt->pci_msi_count) == 0) { 545166721Sjhb iqd = 1; 546166721Sjhb } else { 547166721Sjhb mpt->pci_msi_count = 0; 548166721Sjhb } 549164416Smjacob } 550166721Sjhb if (iqd == 0 && pci_msi_count(dev) == 1) { 551166721Sjhb mpt->pci_msi_count = 1; 552166721Sjhb if (pci_alloc_msi(dev, &mpt->pci_msi_count) == 0) { 553166721Sjhb iqd = 1; 554166721Sjhb } else { 555166721Sjhb mpt->pci_msi_count = 0; 556166721Sjhb } 557166721Sjhb } 558166721Sjhb } 559127135Snjl mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, 560127135Snjl RF_ACTIVE | RF_SHAREABLE); 561101704Smjacob if (mpt->pci_irq == NULL) { 562101704Smjacob device_printf(dev, "could not allocate interrupt\n"); 563101704Smjacob goto bad; 564101704Smjacob } 565101704Smjacob 566147883Sscottl MPT_LOCK_SETUP(mpt); 567147883Sscottl 568147883Sscottl /* Disable interrupts at the part */ 569147883Sscottl mpt_disable_ints(mpt); 570147883Sscottl 571101704Smjacob /* Register the interrupt handler */ 572166935Smjacob if (mpt_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr, 573101704Smjacob mpt, &mpt->ih)) { 574101704Smjacob device_printf(dev, "could not setup interrupt\n"); 575101704Smjacob goto bad; 576101704Smjacob } 577101704Smjacob 578101704Smjacob /* Allocate dma memory */ 579147883Sscottl/* XXX JGibbs -Should really be done based on IOCFacts. */ 580101704Smjacob if (mpt_dma_mem_alloc(mpt)) { 581159091Smjacob mpt_prt(mpt, "Could not allocate DMA memory\n"); 582101704Smjacob goto bad; 583101704Smjacob } 584101704Smjacob 585102199Smjacob /* 586102199Smjacob * Save the PCI config register values 587102199Smjacob * 588102199Smjacob * Hard resets are known to screw up the BAR for diagnostic 589102199Smjacob * memory accesses (Mem1). 590102199Smjacob * 591102199Smjacob * Using Mem1 is known to make the chip stop responding to 592102199Smjacob * configuration space transfers, so we need to save it now 593102199Smjacob */ 594101704Smjacob 595101704Smjacob mpt_read_config_regs(mpt); 596101704Smjacob 597155521Smjacob /* 598155521Smjacob * Disable PIO until we need it 599155521Smjacob */ 600159919Smjacob if (mpt->is_sas) { 601159919Smjacob pci_disable_io(dev, SYS_RES_IOPORT); 602159919Smjacob } 603155521Smjacob 604101704Smjacob /* Initialize the hardware */ 605101704Smjacob if (mpt->disabled == 0) { 606147883Sscottl if (mpt_attach(mpt) != 0) { 607101704Smjacob goto bad; 608102199Smjacob } 609157117Smjacob } else { 610157117Smjacob mpt_prt(mpt, "device disabled at user request\n"); 611157117Smjacob goto bad; 612101704Smjacob } 613101704Smjacob 614157117Smjacob mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown, 615157117Smjacob dev, SHUTDOWN_PRI_DEFAULT); 616157117Smjacob 617157117Smjacob if (mpt->eh == NULL) { 618157117Smjacob mpt_prt(mpt, "shutdown event registration failed\n"); 619157117Smjacob (void) mpt_detach(mpt); 620157117Smjacob goto bad; 621157117Smjacob } 622101704Smjacob return (0); 623101704Smjacob 624101704Smjacobbad: 625101704Smjacob mpt_dma_mem_free(mpt); 626101704Smjacob mpt_free_bus_resources(mpt); 627157662Smjacob mpt_unlink_peer(mpt); 628101704Smjacob 629157662Smjacob MPT_LOCK_DESTROY(mpt); 630157662Smjacob 631101704Smjacob /* 632101704Smjacob * but return zero to preserve unit numbering 633101704Smjacob */ 634101704Smjacob return (0); 635101704Smjacob} 636101704Smjacob 637102199Smjacob/* 638101704Smjacob * Free bus resources 639101704Smjacob */ 640101704Smjacobstatic void 641147883Sscottlmpt_free_bus_resources(struct mpt_softc *mpt) 642101704Smjacob{ 643101704Smjacob if (mpt->ih) { 644101704Smjacob bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih); 645101704Smjacob mpt->ih = 0; 646101704Smjacob } 647101704Smjacob 648101704Smjacob if (mpt->pci_irq) { 649164305Sjhb bus_release_resource(mpt->dev, SYS_RES_IRQ, 650164305Sjhb mpt->pci_msi_count ? 1 : 0, mpt->pci_irq); 651101704Smjacob mpt->pci_irq = 0; 652101704Smjacob } 653101704Smjacob 654164305Sjhb if (mpt->pci_msi_count) { 655164305Sjhb pci_release_msi(mpt->dev); 656164305Sjhb mpt->pci_msi_count = 0; 657164305Sjhb } 658164305Sjhb 659147883Sscottl if (mpt->pci_pio_reg) { 660147883Sscottl bus_release_resource(mpt->dev, SYS_RES_IOPORT, mpt->pci_pio_rid, 661147883Sscottl mpt->pci_pio_reg); 662147883Sscottl mpt->pci_pio_reg = 0; 663147883Sscottl } 664101704Smjacob if (mpt->pci_reg) { 665147883Sscottl bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_rid, 666101704Smjacob mpt->pci_reg); 667101704Smjacob mpt->pci_reg = 0; 668101704Smjacob } 669102199Smjacob MPT_LOCK_DESTROY(mpt); 670101704Smjacob} 671101704Smjacob 672101704Smjacob 673102199Smjacob/* 674101704Smjacob * Disconnect ourselves from the system. 675101704Smjacob */ 676101704Smjacobstatic int 677147883Sscottlmpt_pci_detach(device_t dev) 678101704Smjacob{ 679147883Sscottl struct mpt_softc *mpt; 680101704Smjacob 681147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 682101704Smjacob 683101704Smjacob if (mpt) { 684101704Smjacob mpt_disable_ints(mpt); 685147883Sscottl mpt_detach(mpt); 686147883Sscottl mpt_reset(mpt, /*reinit*/FALSE); 687101704Smjacob mpt_dma_mem_free(mpt); 688101704Smjacob mpt_free_bus_resources(mpt); 689158982Smjacob mpt_raid_free_mem(mpt); 690158982Smjacob if (mpt->eh != NULL) { 691180152Sjhb EVENTHANDLER_DEREGISTER(shutdown_post_sync, mpt->eh); 692147883Sscottl } 693101704Smjacob } 694101704Smjacob return(0); 695101704Smjacob} 696101704Smjacob 697101704Smjacob 698102199Smjacob/* 699101704Smjacob * Disable the hardware 700101704Smjacob */ 701101704Smjacobstatic int 702147883Sscottlmpt_pci_shutdown(device_t dev) 703101704Smjacob{ 704147883Sscottl struct mpt_softc *mpt; 705101704Smjacob 706147883Sscottl mpt = (struct mpt_softc *)device_get_softc(dev); 707157117Smjacob if (mpt) { 708157117Smjacob int r; 709157117Smjacob r = mpt_shutdown(mpt); 710157117Smjacob return (r); 711157117Smjacob } 712101704Smjacob return(0); 713101704Smjacob} 714101704Smjacob 715101704Smjacobstatic int 716147883Sscottlmpt_dma_mem_alloc(struct mpt_softc *mpt) 717101704Smjacob{ 718155521Smjacob int i, error, nsegs; 719147883Sscottl uint8_t *vptr; 720147883Sscottl uint32_t pptr, end; 721103871Smjacob size_t len; 722147883Sscottl struct mpt_map_info mi; 723101704Smjacob 724101704Smjacob /* Check if we alreay have allocated the reply memory */ 725123740Speter if (mpt->reply_phys != 0) { 726101704Smjacob return 0; 727103871Smjacob } 728101704Smjacob 729147883Sscottl len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt); 730103871Smjacob#ifdef RELENG_4 731147883Sscottl mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK); 732103871Smjacob if (mpt->request_pool == NULL) { 733159091Smjacob mpt_prt(mpt, "cannot allocate request pool\n"); 734103871Smjacob return (1); 735103871Smjacob } 736157354Smjacob memset(mpt->request_pool, 0, len); 737103871Smjacob#else 738147883Sscottl mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 739103871Smjacob if (mpt->request_pool == NULL) { 740159091Smjacob mpt_prt(mpt, "cannot allocate request pool\n"); 741103871Smjacob return (1); 742103871Smjacob } 743103871Smjacob#endif 744103871Smjacob 745101704Smjacob /* 746155521Smjacob * Create a parent dma tag for this device. 747101704Smjacob * 748159091Smjacob * Align at byte boundaries, 749159091Smjacob * Limit to 32-bit addressing for request/reply queues. 750101704Smjacob */ 751164314Sjb if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev), 752164314Sjb /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, 753147883Sscottl /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, 754147883Sscottl /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 755147883Sscottl /*nsegments*/BUS_SPACE_MAXSIZE_32BIT, 756147883Sscottl /*maxsegsz*/BUS_SPACE_UNRESTRICTED, /*flags*/0, 757147883Sscottl &mpt->parent_dmat) != 0) { 758159091Smjacob mpt_prt(mpt, "cannot create parent dma tag\n"); 759101704Smjacob return (1); 760101704Smjacob } 761101704Smjacob 762101704Smjacob /* Create a child tag for reply buffers */ 763159091Smjacob if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 764159091Smjacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 765155521Smjacob NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0, 766147883Sscottl &mpt->reply_dmat) != 0) { 767159091Smjacob mpt_prt(mpt, "cannot create a dma tag for replies\n"); 768101704Smjacob return (1); 769101704Smjacob } 770101704Smjacob 771101704Smjacob /* Allocate some DMA accessable memory for replies */ 772101704Smjacob if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply, 773101704Smjacob BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) { 774159091Smjacob mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n", 775155521Smjacob (u_long) (2 * PAGE_SIZE)); 776101704Smjacob return (1); 777101704Smjacob } 778101704Smjacob 779147883Sscottl mi.mpt = mpt; 780147883Sscottl mi.error = 0; 781101704Smjacob 782101704Smjacob /* Load and lock it into "bus space" */ 783101704Smjacob bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply, 784155521Smjacob 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0); 785101704Smjacob 786147883Sscottl if (mi.error) { 787159091Smjacob mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n", 788159091Smjacob mi.error); 789101704Smjacob return (1); 790101704Smjacob } 791147883Sscottl mpt->reply_phys = mi.phys; 792101704Smjacob 793101704Smjacob /* Create a child tag for data buffers */ 794155521Smjacob 795155521Smjacob /* 796155521Smjacob * XXX: we should say that nsegs is 'unrestricted, but that 797155521Smjacob * XXX: tickles a horrible bug in the busdma code. Instead, 798155521Smjacob * XXX: we'll derive a reasonable segment limit from MAXPHYS 799155521Smjacob */ 800155521Smjacob nsegs = (MAXPHYS / PAGE_SIZE) + 1; 801147883Sscottl if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 802101704Smjacob 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 803155521Smjacob NULL, NULL, MAXBSIZE, nsegs, BUS_SPACE_MAXSIZE_32BIT, 0, 804147883Sscottl &mpt->buffer_dmat) != 0) { 805159091Smjacob mpt_prt(mpt, "cannot create a dma tag for data buffers\n"); 806101704Smjacob return (1); 807101704Smjacob } 808101704Smjacob 809101704Smjacob /* Create a child tag for request buffers */ 810159091Smjacob if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 811159091Smjacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 812103871Smjacob NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0, 813147883Sscottl &mpt->request_dmat) != 0) { 814159091Smjacob mpt_prt(mpt, "cannot create a dma tag for requests\n"); 815101704Smjacob return (1); 816101704Smjacob } 817101704Smjacob 818101704Smjacob /* Allocate some DMA accessable memory for requests */ 819101704Smjacob if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request, 820101704Smjacob BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) { 821159091Smjacob mpt_prt(mpt, "cannot allocate %d bytes of request memory\n", 822103871Smjacob MPT_REQ_MEM_SIZE(mpt)); 823101704Smjacob return (1); 824101704Smjacob } 825101704Smjacob 826147883Sscottl mi.mpt = mpt; 827147883Sscottl mi.error = 0; 828101704Smjacob 829101704Smjacob /* Load and lock it into "bus space" */ 830101704Smjacob bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request, 831147883Sscottl MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0); 832101704Smjacob 833147883Sscottl if (mi.error) { 834159091Smjacob mpt_prt(mpt, "error %d loading dma map for DMA request queue\n", 835147883Sscottl mi.error); 836101704Smjacob return (1); 837101704Smjacob } 838147883Sscottl mpt->request_phys = mi.phys; 839101704Smjacob 840159091Smjacob /* 841159091Smjacob * Now create per-request dma maps 842159091Smjacob */ 843101704Smjacob i = 0; 844101704Smjacob pptr = mpt->request_phys; 845101704Smjacob vptr = mpt->request; 846103871Smjacob end = pptr + MPT_REQ_MEM_SIZE(mpt); 847101704Smjacob while(pptr < end) { 848103871Smjacob request_t *req = &mpt->request_pool[i]; 849101704Smjacob req->index = i++; 850101704Smjacob 851101704Smjacob /* Store location of Request Data */ 852101704Smjacob req->req_pbuf = pptr; 853101704Smjacob req->req_vbuf = vptr; 854101704Smjacob 855101704Smjacob pptr += MPT_REQUEST_AREA; 856101704Smjacob vptr += MPT_REQUEST_AREA; 857101704Smjacob 858101704Smjacob req->sense_pbuf = (pptr - MPT_SENSE_SIZE); 859101704Smjacob req->sense_vbuf = (vptr - MPT_SENSE_SIZE); 860101704Smjacob 861101704Smjacob error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap); 862101704Smjacob if (error) { 863159091Smjacob mpt_prt(mpt, "error %d creating per-cmd DMA maps\n", 864159091Smjacob error); 865101704Smjacob return (1); 866101704Smjacob } 867101704Smjacob } 868159091Smjacob 869101704Smjacob return (0); 870101704Smjacob} 871101704Smjacob 872101704Smjacob 873101704Smjacob 874101704Smjacob/* Deallocate memory that was allocated by mpt_dma_mem_alloc 875101704Smjacob */ 876101704Smjacobstatic void 877147883Sscottlmpt_dma_mem_free(struct mpt_softc *mpt) 878101704Smjacob{ 879101704Smjacob int i; 880101704Smjacob 881101704Smjacob /* Make sure we aren't double destroying */ 882101704Smjacob if (mpt->reply_dmat == 0) { 883159091Smjacob mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n"); 884101704Smjacob return; 885101704Smjacob } 886101704Smjacob 887103871Smjacob for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) { 888103871Smjacob bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap); 889101704Smjacob } 890101704Smjacob bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap); 891101704Smjacob bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap); 892101704Smjacob bus_dma_tag_destroy(mpt->request_dmat); 893101704Smjacob bus_dma_tag_destroy(mpt->buffer_dmat); 894101704Smjacob bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap); 895101704Smjacob bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap); 896101704Smjacob bus_dma_tag_destroy(mpt->reply_dmat); 897101704Smjacob bus_dma_tag_destroy(mpt->parent_dmat); 898101704Smjacob mpt->reply_dmat = 0; 899103871Smjacob free(mpt->request_pool, M_DEVBUF); 900103871Smjacob mpt->request_pool = 0; 901101704Smjacob 902101704Smjacob} 903101704Smjacob 904101704Smjacob 905101704Smjacob 906101704Smjacob/* Reads modifiable (via PCI transactions) config registers */ 907101704Smjacobstatic void 908147883Sscottlmpt_read_config_regs(struct mpt_softc *mpt) 909101704Smjacob{ 910101704Smjacob mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2); 911101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize = 912101704Smjacob pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2); 913119690Sjhb mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4); 914119690Sjhb mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4); 915119690Sjhb mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4); 916119690Sjhb mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4); 917119690Sjhb mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4); 918101704Smjacob mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4); 919101704Smjacob mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1); 920101704Smjacob mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4); 921101704Smjacob} 922101704Smjacob 923101704Smjacob/* Sets modifiable config registers */ 924101704Smjacobvoid 925147883Sscottlmpt_set_config_regs(struct mpt_softc *mpt) 926101704Smjacob{ 927147883Sscottl uint32_t val; 928101704Smjacob 929101704Smjacob#define MPT_CHECK(reg, offset, size) \ 930101704Smjacob val = pci_read_config(mpt->dev, offset, size); \ 931101704Smjacob if (mpt->pci_cfg.reg != val) { \ 932103914Smjacob mpt_prt(mpt, \ 933101704Smjacob "Restoring " #reg " to 0x%X from 0x%X\n", \ 934101704Smjacob mpt->pci_cfg.reg, val); \ 935101704Smjacob } 936101704Smjacob 937147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 938101704Smjacob MPT_CHECK(Command, PCIR_COMMAND, 2); 939101704Smjacob MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2); 940119690Sjhb MPT_CHECK(IO_BAR, PCIR_BAR(0), 4); 941119690Sjhb MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4); 942119690Sjhb MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4); 943119690Sjhb MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4); 944119690Sjhb MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4); 945101704Smjacob MPT_CHECK(ROM_BAR, PCIR_BIOS, 4); 946101704Smjacob MPT_CHECK(IntLine, PCIR_INTLINE, 1); 947101704Smjacob MPT_CHECK(PMCSR, 0x44, 4); 948101704Smjacob } 949101704Smjacob#undef MPT_CHECK 950101704Smjacob 951101704Smjacob pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2); 952101704Smjacob pci_write_config(mpt->dev, PCIR_CACHELNSZ, 953101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize, 2); 954119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4); 955119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4); 956119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4); 957119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4); 958119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4); 959101704Smjacob pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4); 960101704Smjacob pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1); 961101704Smjacob pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4); 962101704Smjacob} 963102199Smjacob 964102199Smjacobstatic void 965102199Smjacobmpt_pci_intr(void *arg) 966102199Smjacob{ 967147883Sscottl struct mpt_softc *mpt; 968147883Sscottl 969147883Sscottl mpt = (struct mpt_softc *)arg; 970102199Smjacob MPT_LOCK(mpt); 971147883Sscottl mpt_intr(mpt); 972102199Smjacob MPT_UNLOCK(mpt); 973102199Smjacob} 974