mpt_pci.c revision 160290
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 160290 2006-07-12 07:48:50Z mjacob $"); 103119418Sobrien 104147883Sscottl#include <dev/mpt/mpt.h> 105147883Sscottl#include <dev/mpt/mpt_cam.h> 106147883Sscottl#include <dev/mpt/mpt_raid.h> 107102199Smjacob 108101704Smjacob 109101704Smjacob#ifndef PCI_VENDOR_LSI 110101704Smjacob#define PCI_VENDOR_LSI 0x1000 111101704Smjacob#endif 112101704Smjacob 113101704Smjacob#ifndef PCI_PRODUCT_LSI_FC909 114101704Smjacob#define PCI_PRODUCT_LSI_FC909 0x0620 115101704Smjacob#endif 116101704Smjacob 117102596Smjacob#ifndef PCI_PRODUCT_LSI_FC909A 118102596Smjacob#define PCI_PRODUCT_LSI_FC909A 0x0621 119102596Smjacob#endif 120102596Smjacob 121103829Smjacob#ifndef PCI_PRODUCT_LSI_FC919 122103829Smjacob#define PCI_PRODUCT_LSI_FC919 0x0624 123103829Smjacob#endif 124103829Smjacob 125101704Smjacob#ifndef PCI_PRODUCT_LSI_FC929 126101704Smjacob#define PCI_PRODUCT_LSI_FC929 0x0622 127101704Smjacob#endif 128101704Smjacob 129150007Smjacob#ifndef PCI_PRODUCT_LSI_FC929X 130150007Smjacob#define PCI_PRODUCT_LSI_FC929X 0x0626 131150007Smjacob#endif 132150007Smjacob 133159494Smjacob#ifndef PCI_PRODUCT_LSI_FC919X 134159494Smjacob#define PCI_PRODUCT_LSI_FC919X 0x0628 135159494Smjacob#endif 136159494Smjacob 137158279Smjacob#ifndef PCI_PRODUCT_LSI_FC7X04X 138158279Smjacob#define PCI_PRODUCT_LSI_FC7X04X 0x0640 139158279Smjacob#endif 140158279Smjacob 141101704Smjacob#ifndef PCI_PRODUCT_LSI_1030 142101704Smjacob#define PCI_PRODUCT_LSI_1030 0x0030 143101704Smjacob#endif 144101704Smjacob 145155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064 146155521Smjacob#define PCI_PRODUCT_LSI_SAS1064 0x0050 147155521Smjacob#endif 148155521Smjacob 149155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064A 150155521Smjacob#define PCI_PRODUCT_LSI_SAS1064A 0x005C 151155521Smjacob#endif 152155521Smjacob 153155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1064E 154155521Smjacob#define PCI_PRODUCT_LSI_SAS1064E 0x0056 155155521Smjacob#endif 156155521Smjacob 157155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1066 158155521Smjacob#define PCI_PRODUCT_LSI_SAS1066 0x005E 159155521Smjacob#endif 160155521Smjacob 161155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1066E 162155521Smjacob#define PCI_PRODUCT_LSI_SAS1066E 0x005A 163155521Smjacob#endif 164155521Smjacob 165155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1068 166155521Smjacob#define PCI_PRODUCT_LSI_SAS1068 0x0054 167155521Smjacob#endif 168155521Smjacob 169155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1068E 170155521Smjacob#define PCI_PRODUCT_LSI_SAS1068E 0x0058 171155521Smjacob#endif 172155521Smjacob 173155521Smjacob#ifndef PCI_PRODUCT_LSI_SAS1078 174155521Smjacob#define PCI_PRODUCT_LSI_SAS1078 0x0060 175155521Smjacob#endif 176155521Smjacob 177102303Smjacob#ifndef PCIM_CMD_SERRESPEN 178102303Smjacob#define PCIM_CMD_SERRESPEN 0x0100 179102303Smjacob#endif 180101704Smjacob 181101704Smjacob 182147883Sscottl#define MPT_IO_BAR 0 183147883Sscottl#define MPT_MEM_BAR 1 184101704Smjacob 185147883Sscottlstatic int mpt_pci_probe(device_t); 186147883Sscottlstatic int mpt_pci_attach(device_t); 187147883Sscottlstatic void mpt_free_bus_resources(struct mpt_softc *mpt); 188147883Sscottlstatic int mpt_pci_detach(device_t); 189147883Sscottlstatic int mpt_pci_shutdown(device_t); 190147883Sscottlstatic int mpt_dma_mem_alloc(struct mpt_softc *mpt); 191147883Sscottlstatic void mpt_dma_mem_free(struct mpt_softc *mpt); 192147883Sscottlstatic void mpt_read_config_regs(struct mpt_softc *mpt); 193102199Smjacobstatic void mpt_pci_intr(void *); 194101704Smjacob 195101704Smjacobstatic device_method_t mpt_methods[] = { 196101704Smjacob /* Device interface */ 197147883Sscottl DEVMETHOD(device_probe, mpt_pci_probe), 198147883Sscottl DEVMETHOD(device_attach, mpt_pci_attach), 199147883Sscottl DEVMETHOD(device_detach, mpt_pci_detach), 200147883Sscottl DEVMETHOD(device_shutdown, mpt_pci_shutdown), 201101704Smjacob { 0, 0 } 202101704Smjacob}; 203101704Smjacob 204101704Smjacobstatic driver_t mpt_driver = { 205147883Sscottl "mpt", mpt_methods, sizeof(struct mpt_softc) 206101704Smjacob}; 207101704Smjacobstatic devclass_t mpt_devclass; 208101704SmjacobDRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0); 209101704SmjacobMODULE_VERSION(mpt, 1); 210101704Smjacob 211101704Smjacobstatic int 212147883Sscottlmpt_pci_probe(device_t dev) 213101704Smjacob{ 214101704Smjacob char *desc; 215101704Smjacob 216160290Smjacob if (pci_get_vendor(dev) != PCI_VENDOR_LSI) { 217101704Smjacob return (ENXIO); 218160290Smjacob } 219101704Smjacob 220101704Smjacob switch ((pci_get_device(dev) & ~1)) { 221101704Smjacob case PCI_PRODUCT_LSI_FC909: 222101704Smjacob desc = "LSILogic FC909 FC Adapter"; 223101704Smjacob break; 224102596Smjacob case PCI_PRODUCT_LSI_FC909A: 225102596Smjacob desc = "LSILogic FC909A FC Adapter"; 226102596Smjacob break; 227103829Smjacob case PCI_PRODUCT_LSI_FC919: 228103829Smjacob desc = "LSILogic FC919 FC Adapter"; 229103829Smjacob break; 230101704Smjacob case PCI_PRODUCT_LSI_FC929: 231101704Smjacob desc = "LSILogic FC929 FC Adapter"; 232101704Smjacob break; 233159494Smjacob case PCI_PRODUCT_LSI_FC919X: 234159494Smjacob desc = "LSILogic FC919X FC Adapter"; 235159494Smjacob break; 236150007Smjacob case PCI_PRODUCT_LSI_FC929X: 237158279Smjacob desc = "LSILogic FC929X 2Gb/s FC Adapter"; 238150007Smjacob break; 239158279Smjacob case PCI_PRODUCT_LSI_FC7X04X: 240158279Smjacob desc = "LSILogic FC7X04X 4Gb/s FC Adapter"; 241158279Smjacob break; 242101704Smjacob case PCI_PRODUCT_LSI_1030: 243101704Smjacob desc = "LSILogic 1030 Ultra4 Adapter"; 244101704Smjacob break; 245155521Smjacob case PCI_PRODUCT_LSI_SAS1064: 246155521Smjacob case PCI_PRODUCT_LSI_SAS1064A: 247155521Smjacob case PCI_PRODUCT_LSI_SAS1064E: 248155521Smjacob case PCI_PRODUCT_LSI_SAS1066: 249155521Smjacob case PCI_PRODUCT_LSI_SAS1066E: 250155521Smjacob case PCI_PRODUCT_LSI_SAS1068: 251155521Smjacob case PCI_PRODUCT_LSI_SAS1068E: 252155521Smjacob case PCI_PRODUCT_LSI_SAS1078: 253155521Smjacob desc = "LSILogic SAS Adapter"; 254155521Smjacob break; 255101704Smjacob default: 256101704Smjacob return (ENXIO); 257101704Smjacob } 258101704Smjacob 259101704Smjacob device_set_desc(dev, desc); 260147883Sscottl return (0); 261101704Smjacob} 262101704Smjacob 263157117Smjacob#if __FreeBSD_version < 500000 264101704Smjacobstatic void 265147883Sscottlmpt_set_options(struct mpt_softc *mpt) 266101704Smjacob{ 267101704Smjacob int bitmap; 268101704Smjacob 269101704Smjacob bitmap = 0; 270101704Smjacob if (getenv_int("mpt_disable", &bitmap)) { 271101704Smjacob if (bitmap & (1 << mpt->unit)) { 272101704Smjacob mpt->disabled = 1; 273101704Smjacob } 274101704Smjacob } 275101704Smjacob bitmap = 0; 276101704Smjacob if (getenv_int("mpt_debug", &bitmap)) { 277101704Smjacob if (bitmap & (1 << mpt->unit)) { 278147883Sscottl mpt->verbose = MPT_PRT_DEBUG; 279101704Smjacob } 280101704Smjacob } 281157117Smjacob bitmap = 0; 282157662Smjacob if (getenv_int("mpt_debug1", &bitmap)) { 283157117Smjacob if (bitmap & (1 << mpt->unit)) { 284157662Smjacob mpt->verbose = MPT_PRT_DEBUG1; 285157117Smjacob } 286157117Smjacob } 287157117Smjacob bitmap = 0; 288157662Smjacob if (getenv_int("mpt_debug2", &bitmap)) { 289157117Smjacob if (bitmap & (1 << mpt->unit)) { 290157662Smjacob mpt->verbose = MPT_PRT_DEBUG2; 291157117Smjacob } 292157117Smjacob } 293157117Smjacob bitmap = 0; 294157662Smjacob if (getenv_int("mpt_debug3", &bitmap)) { 295157117Smjacob if (bitmap & (1 << mpt->unit)) { 296157662Smjacob mpt->verbose = MPT_PRT_DEBUG3; 297157117Smjacob } 298157117Smjacob } 299160290Smjacob 300160290Smjacob mpt->cfg_role = MPT_ROLE_DEFAULT; 301160290Smjacob bitmap = 0; 302160290Smjacob if (getenv_int("mpt_nil_role", &bitmap)) { 303160290Smjacob if (bitmap & (1 << mpt->unit)) { 304160290Smjacob mpt->cfg_role = 0; 305160290Smjacob } 306160290Smjacob mpt->do_cfg_role = 1; 307160290Smjacob } 308160290Smjacob bitmap = 0; 309160290Smjacob if (getenv_int("mpt_tgt_role", &bitmap)) { 310160290Smjacob if (bitmap & (1 << mpt->unit)) { 311160290Smjacob mpt->cfg_role |= MPT_ROLE_TARGET; 312160290Smjacob } 313160290Smjacob mpt->do_cfg_role = 1; 314160290Smjacob } 315160290Smjacob bitmap = 0; 316160290Smjacob if (getenv_int("mpt_ini_role", &bitmap)) { 317160290Smjacob if (bitmap & (1 << mpt->unit)) { 318160290Smjacob mpt->cfg_role |= MPT_ROLE_INITIATOR; 319160290Smjacob } 320160290Smjacob mpt->do_cfg_role = 1; 321160290Smjacob } 322101704Smjacob} 323101704Smjacob#else 324101704Smjacobstatic void 325147883Sscottlmpt_set_options(struct mpt_softc *mpt) 326101704Smjacob{ 327101704Smjacob int tval; 328101704Smjacob 329101704Smjacob tval = 0; 330101704Smjacob if (resource_int_value(device_get_name(mpt->dev), 331101704Smjacob device_get_unit(mpt->dev), "disable", &tval) == 0 && tval != 0) { 332101704Smjacob mpt->disabled = 1; 333101704Smjacob } 334101704Smjacob tval = 0; 335101704Smjacob if (resource_int_value(device_get_name(mpt->dev), 336101704Smjacob device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { 337159041Smjacob mpt->verbose = tval; 338101704Smjacob } 339160290Smjacob tval = -1; 340157117Smjacob if (resource_int_value(device_get_name(mpt->dev), 341160290Smjacob device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && 342157117Smjacob tval <= 3) { 343160290Smjacob mpt->cfg_role = tval; 344160290Smjacob mpt->do_cfg_role = 1; 345157117Smjacob } 346101704Smjacob} 347101704Smjacob#endif 348101704Smjacob 349101704Smjacob 350102303Smjacobstatic void 351147883Sscottlmpt_link_peer(struct mpt_softc *mpt) 352102303Smjacob{ 353147883Sscottl struct mpt_softc *mpt2; 354102303Smjacob 355157662Smjacob if (mpt->unit == 0) { 356102303Smjacob return; 357157662Smjacob } 358102303Smjacob /* 359102303Smjacob * XXX: depends on probe order 360102303Smjacob */ 361147883Sscottl mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1); 362102303Smjacob 363102303Smjacob if (mpt2 == NULL) { 364102303Smjacob return; 365102303Smjacob } 366102303Smjacob if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) { 367102303Smjacob return; 368102303Smjacob } 369102303Smjacob if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) { 370102303Smjacob return; 371102303Smjacob } 372102303Smjacob mpt->mpt2 = mpt2; 373102303Smjacob mpt2->mpt2 = mpt; 374147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 375147883Sscottl mpt_prt(mpt, "linking with peer (mpt%d)\n", 376102303Smjacob device_get_unit(mpt2->dev)); 377102303Smjacob } 378102303Smjacob} 379102303Smjacob 380157662Smjacobstatic void 381157662Smjacobmpt_unlink_peer(struct mpt_softc *mpt) 382157662Smjacob{ 383157662Smjacob if (mpt->mpt2) { 384157662Smjacob mpt->mpt2->mpt2 = NULL; 385157662Smjacob } 386157662Smjacob} 387102303Smjacob 388157662Smjacob 389101704Smjacobstatic int 390147883Sscottlmpt_pci_attach(device_t dev) 391101704Smjacob{ 392147883Sscottl struct mpt_softc *mpt; 393147883Sscottl int iqd; 394147883Sscottl uint32_t data, cmd; 395101704Smjacob 396101704Smjacob /* Allocate the softc structure */ 397147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 398101704Smjacob if (mpt == NULL) { 399101704Smjacob device_printf(dev, "cannot allocate softc\n"); 400101704Smjacob return (ENOMEM); 401101704Smjacob } 402157354Smjacob memset(mpt, 0, sizeof(struct mpt_softc)); 403101704Smjacob switch ((pci_get_device(dev) & ~1)) { 404101704Smjacob case PCI_PRODUCT_LSI_FC909: 405102596Smjacob case PCI_PRODUCT_LSI_FC909A: 406103829Smjacob case PCI_PRODUCT_LSI_FC919: 407101704Smjacob case PCI_PRODUCT_LSI_FC929: 408159494Smjacob case PCI_PRODUCT_LSI_FC919X: 409158279Smjacob case PCI_PRODUCT_LSI_FC7X04X: 410101704Smjacob mpt->is_fc = 1; 411101704Smjacob break; 412155521Smjacob case PCI_PRODUCT_LSI_SAS1064: 413155521Smjacob case PCI_PRODUCT_LSI_SAS1064A: 414155521Smjacob case PCI_PRODUCT_LSI_SAS1064E: 415155521Smjacob case PCI_PRODUCT_LSI_SAS1066: 416155521Smjacob case PCI_PRODUCT_LSI_SAS1066E: 417155521Smjacob case PCI_PRODUCT_LSI_SAS1068: 418155521Smjacob case PCI_PRODUCT_LSI_SAS1068E: 419155521Smjacob case PCI_PRODUCT_LSI_SAS1078: 420155521Smjacob mpt->is_sas = 1; 421155521Smjacob break; 422101704Smjacob default: 423159178Smjacob mpt->is_spi = 1; 424101704Smjacob break; 425101704Smjacob } 426101704Smjacob mpt->dev = dev; 427101704Smjacob mpt->unit = device_get_unit(dev); 428147883Sscottl mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT; 429147883Sscottl mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; 430147883Sscottl mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; 431155521Smjacob mpt->verbose = MPT_PRT_NONE; 432157662Smjacob mpt->role = MPT_ROLE_NONE; 433101704Smjacob mpt_set_options(mpt); 434155521Smjacob if (mpt->verbose == MPT_PRT_NONE) { 435155521Smjacob mpt->verbose = MPT_PRT_WARN; 436155521Smjacob /* Print INFO level (if any) if bootverbose is set */ 437155521Smjacob mpt->verbose += (bootverbose != 0)? 1 : 0; 438155521Smjacob } 439101704Smjacob /* Make sure memory access decoders are enabled */ 440101704Smjacob cmd = pci_read_config(dev, PCIR_COMMAND, 2); 441101704Smjacob if ((cmd & PCIM_CMD_MEMEN) == 0) { 442101704Smjacob device_printf(dev, "Memory accesses disabled"); 443157662Smjacob return (ENXIO); 444101704Smjacob } 445101704Smjacob 446101704Smjacob /* 447101704Smjacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 448101704Smjacob */ 449101704Smjacob cmd |= 450101704Smjacob PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | 451101704Smjacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 452101704Smjacob pci_write_config(dev, PCIR_COMMAND, cmd, 2); 453101704Smjacob 454101704Smjacob /* 455101704Smjacob * Make sure we've disabled the ROM. 456101704Smjacob */ 457101704Smjacob data = pci_read_config(dev, PCIR_BIOS, 4); 458101704Smjacob data &= ~1; 459101704Smjacob pci_write_config(dev, PCIR_BIOS, data, 4); 460101704Smjacob 461102303Smjacob /* 462102303Smjacob * Is this part a dual? 463102303Smjacob * If so, link with our partner (around yet) 464102303Smjacob */ 465102303Smjacob if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929 || 466158279Smjacob (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC7X04X || 467102303Smjacob (pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_1030) { 468102303Smjacob mpt_link_peer(mpt); 469101704Smjacob } 470101704Smjacob 471147883Sscottl /* 472147883Sscottl * Set up register access. PIO mode is required for 473155521Smjacob * certain reset operations (but must be disabled for 474155521Smjacob * some cards otherwise). 475147883Sscottl */ 476147883Sscottl mpt->pci_pio_rid = PCIR_BAR(MPT_IO_BAR); 477147883Sscottl mpt->pci_pio_reg = bus_alloc_resource(dev, SYS_RES_IOPORT, 478147883Sscottl &mpt->pci_pio_rid, 0, ~0, 0, RF_ACTIVE); 479147883Sscottl if (mpt->pci_pio_reg == NULL) { 480147883Sscottl device_printf(dev, "unable to map registers in PIO mode\n"); 481147883Sscottl goto bad; 482147883Sscottl } 483147883Sscottl mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); 484147883Sscottl mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); 485147883Sscottl 486101704Smjacob /* Allocate kernel virtual memory for the 9x9's Mem0 region */ 487147883Sscottl mpt->pci_mem_rid = PCIR_BAR(MPT_MEM_BAR); 488101704Smjacob mpt->pci_reg = bus_alloc_resource(dev, SYS_RES_MEMORY, 489147883Sscottl &mpt->pci_mem_rid, 0, ~0, 0, RF_ACTIVE); 490101704Smjacob if (mpt->pci_reg == NULL) { 491147883Sscottl device_printf(dev, "Unable to memory map registers.\n"); 492155521Smjacob if (mpt->is_sas) { 493155521Smjacob device_printf(dev, "Giving Up.\n"); 494155521Smjacob goto bad; 495155521Smjacob } 496147883Sscottl device_printf(dev, "Falling back to PIO mode.\n"); 497147883Sscottl mpt->pci_st = mpt->pci_pio_st; 498147883Sscottl mpt->pci_sh = mpt->pci_pio_sh; 499147883Sscottl } else { 500147883Sscottl mpt->pci_st = rman_get_bustag(mpt->pci_reg); 501147883Sscottl mpt->pci_sh = rman_get_bushandle(mpt->pci_reg); 502101704Smjacob } 503101704Smjacob 504101704Smjacob /* Get a handle to the interrupt */ 505101704Smjacob iqd = 0; 506147883Sscottl#if __FreeBSD_version < 500000 507147883Sscottl mpt->pci_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &iqd, 0, ~0, 1, 508147883Sscottl RF_ACTIVE | RF_SHAREABLE); 509147883Sscottl#else 510127135Snjl mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, 511127135Snjl RF_ACTIVE | RF_SHAREABLE); 512147883Sscottl#endif 513101704Smjacob if (mpt->pci_irq == NULL) { 514101704Smjacob device_printf(dev, "could not allocate interrupt\n"); 515101704Smjacob goto bad; 516101704Smjacob } 517101704Smjacob 518147883Sscottl MPT_LOCK_SETUP(mpt); 519147883Sscottl 520147883Sscottl /* Disable interrupts at the part */ 521147883Sscottl mpt_disable_ints(mpt); 522147883Sscottl 523101704Smjacob /* Register the interrupt handler */ 524102199Smjacob if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, mpt_pci_intr, 525101704Smjacob mpt, &mpt->ih)) { 526101704Smjacob device_printf(dev, "could not setup interrupt\n"); 527101704Smjacob goto bad; 528101704Smjacob } 529101704Smjacob 530101704Smjacob /* Allocate dma memory */ 531147883Sscottl/* XXX JGibbs -Should really be done based on IOCFacts. */ 532101704Smjacob if (mpt_dma_mem_alloc(mpt)) { 533159091Smjacob mpt_prt(mpt, "Could not allocate DMA memory\n"); 534101704Smjacob goto bad; 535101704Smjacob } 536101704Smjacob 537102199Smjacob /* 538102199Smjacob * Save the PCI config register values 539102199Smjacob * 540102199Smjacob * Hard resets are known to screw up the BAR for diagnostic 541102199Smjacob * memory accesses (Mem1). 542102199Smjacob * 543102199Smjacob * Using Mem1 is known to make the chip stop responding to 544102199Smjacob * configuration space transfers, so we need to save it now 545102199Smjacob */ 546101704Smjacob 547101704Smjacob mpt_read_config_regs(mpt); 548101704Smjacob 549155521Smjacob /* 550155521Smjacob * Disable PIO until we need it 551155521Smjacob */ 552159919Smjacob if (mpt->is_sas) { 553159919Smjacob pci_disable_io(dev, SYS_RES_IOPORT); 554159919Smjacob } 555155521Smjacob 556101704Smjacob /* Initialize the hardware */ 557101704Smjacob if (mpt->disabled == 0) { 558102199Smjacob MPT_LOCK(mpt); 559147883Sscottl if (mpt_attach(mpt) != 0) { 560102199Smjacob MPT_UNLOCK(mpt); 561101704Smjacob goto bad; 562102199Smjacob } 563157117Smjacob MPT_UNLOCK(mpt); 564157117Smjacob } else { 565157117Smjacob mpt_prt(mpt, "device disabled at user request\n"); 566157117Smjacob goto bad; 567101704Smjacob } 568101704Smjacob 569157117Smjacob mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown, 570157117Smjacob dev, SHUTDOWN_PRI_DEFAULT); 571157117Smjacob 572157117Smjacob if (mpt->eh == NULL) { 573157117Smjacob mpt_prt(mpt, "shutdown event registration failed\n"); 574157117Smjacob MPT_LOCK(mpt); 575157117Smjacob (void) mpt_detach(mpt); 576157117Smjacob MPT_UNLOCK(mpt); 577157117Smjacob goto bad; 578157117Smjacob } 579157662Smjacob KASSERT(MPT_OWNED(mpt) == 0, ("leaving attach with device locked")); 580101704Smjacob return (0); 581101704Smjacob 582101704Smjacobbad: 583101704Smjacob mpt_dma_mem_free(mpt); 584101704Smjacob mpt_free_bus_resources(mpt); 585157662Smjacob mpt_unlink_peer(mpt); 586101704Smjacob 587157662Smjacob MPT_LOCK_DESTROY(mpt); 588157662Smjacob 589101704Smjacob /* 590101704Smjacob * but return zero to preserve unit numbering 591101704Smjacob */ 592101704Smjacob return (0); 593101704Smjacob} 594101704Smjacob 595102199Smjacob/* 596101704Smjacob * Free bus resources 597101704Smjacob */ 598101704Smjacobstatic void 599147883Sscottlmpt_free_bus_resources(struct mpt_softc *mpt) 600101704Smjacob{ 601101704Smjacob if (mpt->ih) { 602101704Smjacob bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih); 603101704Smjacob mpt->ih = 0; 604101704Smjacob } 605101704Smjacob 606101704Smjacob if (mpt->pci_irq) { 607101704Smjacob bus_release_resource(mpt->dev, SYS_RES_IRQ, 0, mpt->pci_irq); 608101704Smjacob mpt->pci_irq = 0; 609101704Smjacob } 610101704Smjacob 611147883Sscottl if (mpt->pci_pio_reg) { 612147883Sscottl bus_release_resource(mpt->dev, SYS_RES_IOPORT, mpt->pci_pio_rid, 613147883Sscottl mpt->pci_pio_reg); 614147883Sscottl mpt->pci_pio_reg = 0; 615147883Sscottl } 616101704Smjacob if (mpt->pci_reg) { 617147883Sscottl bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_rid, 618101704Smjacob mpt->pci_reg); 619101704Smjacob mpt->pci_reg = 0; 620101704Smjacob } 621102199Smjacob MPT_LOCK_DESTROY(mpt); 622101704Smjacob} 623101704Smjacob 624101704Smjacob 625102199Smjacob/* 626101704Smjacob * Disconnect ourselves from the system. 627101704Smjacob */ 628101704Smjacobstatic int 629147883Sscottlmpt_pci_detach(device_t dev) 630101704Smjacob{ 631147883Sscottl struct mpt_softc *mpt; 632101704Smjacob 633147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 634101704Smjacob 635101704Smjacob if (mpt) { 636157117Smjacob MPT_LOCK(mpt); 637101704Smjacob mpt_disable_ints(mpt); 638147883Sscottl mpt_detach(mpt); 639147883Sscottl mpt_reset(mpt, /*reinit*/FALSE); 640101704Smjacob mpt_dma_mem_free(mpt); 641101704Smjacob mpt_free_bus_resources(mpt); 642158982Smjacob mpt_raid_free_mem(mpt); 643158982Smjacob if (mpt->eh != NULL) { 644158982Smjacob EVENTHANDLER_DEREGISTER(shutdown_final, mpt->eh); 645147883Sscottl } 646157117Smjacob MPT_UNLOCK(mpt); 647101704Smjacob } 648101704Smjacob return(0); 649101704Smjacob} 650101704Smjacob 651101704Smjacob 652102199Smjacob/* 653101704Smjacob * Disable the hardware 654101704Smjacob */ 655101704Smjacobstatic int 656147883Sscottlmpt_pci_shutdown(device_t dev) 657101704Smjacob{ 658147883Sscottl struct mpt_softc *mpt; 659101704Smjacob 660147883Sscottl mpt = (struct mpt_softc *)device_get_softc(dev); 661157117Smjacob if (mpt) { 662157117Smjacob int r; 663157117Smjacob MPT_LOCK(mpt); 664157117Smjacob r = mpt_shutdown(mpt); 665157117Smjacob MPT_UNLOCK(mpt); 666157117Smjacob return (r); 667157117Smjacob } 668101704Smjacob return(0); 669101704Smjacob} 670101704Smjacob 671101704Smjacobstatic int 672147883Sscottlmpt_dma_mem_alloc(struct mpt_softc *mpt) 673101704Smjacob{ 674155521Smjacob int i, error, nsegs; 675147883Sscottl uint8_t *vptr; 676147883Sscottl uint32_t pptr, end; 677103871Smjacob size_t len; 678147883Sscottl struct mpt_map_info mi; 679101704Smjacob 680101704Smjacob /* Check if we alreay have allocated the reply memory */ 681123740Speter if (mpt->reply_phys != 0) { 682101704Smjacob return 0; 683103871Smjacob } 684101704Smjacob 685147883Sscottl len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt); 686103871Smjacob#ifdef RELENG_4 687147883Sscottl mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK); 688103871Smjacob if (mpt->request_pool == NULL) { 689159091Smjacob mpt_prt(mpt, "cannot allocate request pool\n"); 690103871Smjacob return (1); 691103871Smjacob } 692157354Smjacob memset(mpt->request_pool, 0, len); 693103871Smjacob#else 694147883Sscottl mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 695103871Smjacob if (mpt->request_pool == NULL) { 696159091Smjacob mpt_prt(mpt, "cannot allocate request pool\n"); 697103871Smjacob return (1); 698103871Smjacob } 699103871Smjacob#endif 700103871Smjacob 701101704Smjacob /* 702155521Smjacob * Create a parent dma tag for this device. 703101704Smjacob * 704159091Smjacob * Align at byte boundaries, 705159091Smjacob * Limit to 32-bit addressing for request/reply queues. 706101704Smjacob */ 707147883Sscottl if (mpt_dma_tag_create(mpt, /*parent*/NULL, /*alignment*/1, 708155521Smjacob /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, 709147883Sscottl /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, 710147883Sscottl /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 711147883Sscottl /*nsegments*/BUS_SPACE_MAXSIZE_32BIT, 712147883Sscottl /*maxsegsz*/BUS_SPACE_UNRESTRICTED, /*flags*/0, 713147883Sscottl &mpt->parent_dmat) != 0) { 714159091Smjacob mpt_prt(mpt, "cannot create parent dma tag\n"); 715101704Smjacob return (1); 716101704Smjacob } 717101704Smjacob 718101704Smjacob /* Create a child tag for reply buffers */ 719159091Smjacob if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 720159091Smjacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 721155521Smjacob NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0, 722147883Sscottl &mpt->reply_dmat) != 0) { 723159091Smjacob mpt_prt(mpt, "cannot create a dma tag for replies\n"); 724101704Smjacob return (1); 725101704Smjacob } 726101704Smjacob 727101704Smjacob /* Allocate some DMA accessable memory for replies */ 728101704Smjacob if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply, 729101704Smjacob BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) { 730159091Smjacob mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n", 731155521Smjacob (u_long) (2 * PAGE_SIZE)); 732101704Smjacob return (1); 733101704Smjacob } 734101704Smjacob 735147883Sscottl mi.mpt = mpt; 736147883Sscottl mi.error = 0; 737101704Smjacob 738101704Smjacob /* Load and lock it into "bus space" */ 739101704Smjacob bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply, 740155521Smjacob 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0); 741101704Smjacob 742147883Sscottl if (mi.error) { 743159091Smjacob mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n", 744159091Smjacob mi.error); 745101704Smjacob return (1); 746101704Smjacob } 747147883Sscottl mpt->reply_phys = mi.phys; 748101704Smjacob 749101704Smjacob /* Create a child tag for data buffers */ 750155521Smjacob 751155521Smjacob /* 752155521Smjacob * XXX: we should say that nsegs is 'unrestricted, but that 753155521Smjacob * XXX: tickles a horrible bug in the busdma code. Instead, 754155521Smjacob * XXX: we'll derive a reasonable segment limit from MAXPHYS 755155521Smjacob */ 756155521Smjacob nsegs = (MAXPHYS / PAGE_SIZE) + 1; 757147883Sscottl if (mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 758101704Smjacob 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 759155521Smjacob NULL, NULL, MAXBSIZE, nsegs, BUS_SPACE_MAXSIZE_32BIT, 0, 760147883Sscottl &mpt->buffer_dmat) != 0) { 761159091Smjacob mpt_prt(mpt, "cannot create a dma tag for data buffers\n"); 762101704Smjacob return (1); 763101704Smjacob } 764101704Smjacob 765101704Smjacob /* Create a child tag for request buffers */ 766159091Smjacob if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 767159091Smjacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 768103871Smjacob NULL, NULL, MPT_REQ_MEM_SIZE(mpt), 1, BUS_SPACE_MAXSIZE_32BIT, 0, 769147883Sscottl &mpt->request_dmat) != 0) { 770159091Smjacob mpt_prt(mpt, "cannot create a dma tag for requests\n"); 771101704Smjacob return (1); 772101704Smjacob } 773101704Smjacob 774101704Smjacob /* Allocate some DMA accessable memory for requests */ 775101704Smjacob if (bus_dmamem_alloc(mpt->request_dmat, (void **)&mpt->request, 776101704Smjacob BUS_DMA_NOWAIT, &mpt->request_dmap) != 0) { 777159091Smjacob mpt_prt(mpt, "cannot allocate %d bytes of request memory\n", 778103871Smjacob MPT_REQ_MEM_SIZE(mpt)); 779101704Smjacob return (1); 780101704Smjacob } 781101704Smjacob 782147883Sscottl mi.mpt = mpt; 783147883Sscottl mi.error = 0; 784101704Smjacob 785101704Smjacob /* Load and lock it into "bus space" */ 786101704Smjacob bus_dmamap_load(mpt->request_dmat, mpt->request_dmap, mpt->request, 787147883Sscottl MPT_REQ_MEM_SIZE(mpt), mpt_map_rquest, &mi, 0); 788101704Smjacob 789147883Sscottl if (mi.error) { 790159091Smjacob mpt_prt(mpt, "error %d loading dma map for DMA request queue\n", 791147883Sscottl mi.error); 792101704Smjacob return (1); 793101704Smjacob } 794147883Sscottl mpt->request_phys = mi.phys; 795101704Smjacob 796159091Smjacob /* 797159091Smjacob * Now create per-request dma maps 798159091Smjacob */ 799101704Smjacob i = 0; 800101704Smjacob pptr = mpt->request_phys; 801101704Smjacob vptr = mpt->request; 802103871Smjacob end = pptr + MPT_REQ_MEM_SIZE(mpt); 803101704Smjacob while(pptr < end) { 804103871Smjacob request_t *req = &mpt->request_pool[i]; 805101704Smjacob req->index = i++; 806101704Smjacob 807101704Smjacob /* Store location of Request Data */ 808101704Smjacob req->req_pbuf = pptr; 809101704Smjacob req->req_vbuf = vptr; 810101704Smjacob 811101704Smjacob pptr += MPT_REQUEST_AREA; 812101704Smjacob vptr += MPT_REQUEST_AREA; 813101704Smjacob 814101704Smjacob req->sense_pbuf = (pptr - MPT_SENSE_SIZE); 815101704Smjacob req->sense_vbuf = (vptr - MPT_SENSE_SIZE); 816101704Smjacob 817101704Smjacob error = bus_dmamap_create(mpt->buffer_dmat, 0, &req->dmap); 818101704Smjacob if (error) { 819159091Smjacob mpt_prt(mpt, "error %d creating per-cmd DMA maps\n", 820159091Smjacob error); 821101704Smjacob return (1); 822101704Smjacob } 823101704Smjacob } 824159091Smjacob 825101704Smjacob return (0); 826101704Smjacob} 827101704Smjacob 828101704Smjacob 829101704Smjacob 830101704Smjacob/* Deallocate memory that was allocated by mpt_dma_mem_alloc 831101704Smjacob */ 832101704Smjacobstatic void 833147883Sscottlmpt_dma_mem_free(struct mpt_softc *mpt) 834101704Smjacob{ 835101704Smjacob int i; 836101704Smjacob 837101704Smjacob /* Make sure we aren't double destroying */ 838101704Smjacob if (mpt->reply_dmat == 0) { 839159091Smjacob mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n"); 840101704Smjacob return; 841101704Smjacob } 842101704Smjacob 843103871Smjacob for (i = 0; i < MPT_MAX_REQUESTS(mpt); i++) { 844103871Smjacob bus_dmamap_destroy(mpt->buffer_dmat, mpt->request_pool[i].dmap); 845101704Smjacob } 846101704Smjacob bus_dmamap_unload(mpt->request_dmat, mpt->request_dmap); 847101704Smjacob bus_dmamem_free(mpt->request_dmat, mpt->request, mpt->request_dmap); 848101704Smjacob bus_dma_tag_destroy(mpt->request_dmat); 849101704Smjacob bus_dma_tag_destroy(mpt->buffer_dmat); 850101704Smjacob bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap); 851101704Smjacob bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap); 852101704Smjacob bus_dma_tag_destroy(mpt->reply_dmat); 853101704Smjacob bus_dma_tag_destroy(mpt->parent_dmat); 854101704Smjacob mpt->reply_dmat = 0; 855103871Smjacob free(mpt->request_pool, M_DEVBUF); 856103871Smjacob mpt->request_pool = 0; 857101704Smjacob 858101704Smjacob} 859101704Smjacob 860101704Smjacob 861101704Smjacob 862101704Smjacob/* Reads modifiable (via PCI transactions) config registers */ 863101704Smjacobstatic void 864147883Sscottlmpt_read_config_regs(struct mpt_softc *mpt) 865101704Smjacob{ 866101704Smjacob mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2); 867101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize = 868101704Smjacob pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2); 869119690Sjhb mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4); 870119690Sjhb mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4); 871119690Sjhb mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4); 872119690Sjhb mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4); 873119690Sjhb mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4); 874101704Smjacob mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4); 875101704Smjacob mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1); 876101704Smjacob mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4); 877101704Smjacob} 878101704Smjacob 879101704Smjacob/* Sets modifiable config registers */ 880101704Smjacobvoid 881147883Sscottlmpt_set_config_regs(struct mpt_softc *mpt) 882101704Smjacob{ 883147883Sscottl uint32_t val; 884101704Smjacob 885101704Smjacob#define MPT_CHECK(reg, offset, size) \ 886101704Smjacob val = pci_read_config(mpt->dev, offset, size); \ 887101704Smjacob if (mpt->pci_cfg.reg != val) { \ 888103914Smjacob mpt_prt(mpt, \ 889101704Smjacob "Restoring " #reg " to 0x%X from 0x%X\n", \ 890101704Smjacob mpt->pci_cfg.reg, val); \ 891101704Smjacob } 892101704Smjacob 893147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 894101704Smjacob MPT_CHECK(Command, PCIR_COMMAND, 2); 895101704Smjacob MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2); 896119690Sjhb MPT_CHECK(IO_BAR, PCIR_BAR(0), 4); 897119690Sjhb MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4); 898119690Sjhb MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4); 899119690Sjhb MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4); 900119690Sjhb MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4); 901101704Smjacob MPT_CHECK(ROM_BAR, PCIR_BIOS, 4); 902101704Smjacob MPT_CHECK(IntLine, PCIR_INTLINE, 1); 903101704Smjacob MPT_CHECK(PMCSR, 0x44, 4); 904101704Smjacob } 905101704Smjacob#undef MPT_CHECK 906101704Smjacob 907101704Smjacob pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2); 908101704Smjacob pci_write_config(mpt->dev, PCIR_CACHELNSZ, 909101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize, 2); 910119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4); 911119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4); 912119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4); 913119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4); 914119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4); 915101704Smjacob pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4); 916101704Smjacob pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1); 917101704Smjacob pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4); 918101704Smjacob} 919102199Smjacob 920102199Smjacobstatic void 921102199Smjacobmpt_pci_intr(void *arg) 922102199Smjacob{ 923147883Sscottl struct mpt_softc *mpt; 924147883Sscottl 925147883Sscottl mpt = (struct mpt_softc *)arg; 926102199Smjacob MPT_LOCK(mpt); 927147883Sscottl mpt_intr(mpt); 928102199Smjacob MPT_UNLOCK(mpt); 929102199Smjacob} 930