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: stable/11/sys/dev/mpt/mpt_pci.c 315808 2017-03-23 06:34:15Z mav $"); 103119418Sobrien 104147883Sscottl#include <dev/mpt/mpt.h> 105147883Sscottl#include <dev/mpt/mpt_cam.h> 106147883Sscottl#include <dev/mpt/mpt_raid.h> 107102199Smjacob 108233403Smarius/* 109233403Smarius * XXX it seems no other MPT driver knows about the following chips. 110233403Smarius */ 111101704Smjacob 112233403Smarius#ifndef MPI_MANUFACTPAGE_DEVICEID_FC909_FB 113233403Smarius#define MPI_MANUFACTPAGE_DEVICEID_FC909_FB 0x0620 114101704Smjacob#endif 115101704Smjacob 116233403Smarius#ifndef MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB 117233403Smarius#define MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB 0x0625 118102596Smjacob#endif 119102596Smjacob 120233403Smarius#ifndef MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB 121233403Smarius#define MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB 0x0623 122103829Smjacob#endif 123103829Smjacob 124233403Smarius#ifndef MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB 125233403Smarius#define MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB 0x0627 126232411Sken#endif 127232411Sken 128233403Smarius#ifndef MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB 129233403Smarius#define MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB 0x0629 130101704Smjacob#endif 131101704Smjacob 132233403Smarius#ifndef MPI_MANUFACTPAGE_DEVID_SAS1068A_FB 133233403Smarius#define MPI_MANUFACTPAGE_DEVID_SAS1068A_FB 0x0055 134232411Sken#endif 135232411Sken 136233827Smarius#ifndef MPI_MANUFACTPAGE_DEVID_SAS1068E_FB 137233827Smarius#define MPI_MANUFACTPAGE_DEVID_SAS1068E_FB 0x0059 138233827Smarius#endif 139233827Smarius 140233403Smarius#ifndef MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB 141233403Smarius#define MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB 0x007C 142150007Smjacob#endif 143150007Smjacob 144147883Sscottlstatic int mpt_pci_probe(device_t); 145147883Sscottlstatic int mpt_pci_attach(device_t); 146147883Sscottlstatic void mpt_free_bus_resources(struct mpt_softc *mpt); 147147883Sscottlstatic int mpt_pci_detach(device_t); 148147883Sscottlstatic int mpt_pci_shutdown(device_t); 149147883Sscottlstatic int mpt_dma_mem_alloc(struct mpt_softc *mpt); 150147883Sscottlstatic void mpt_dma_mem_free(struct mpt_softc *mpt); 151233403Smarius#if 0 152147883Sscottlstatic void mpt_read_config_regs(struct mpt_softc *mpt); 153224493Smariusstatic void mpt_set_config_regs(struct mpt_softc *mpt); 154224493Smarius#endif 155102199Smjacobstatic void mpt_pci_intr(void *); 156101704Smjacob 157101704Smjacobstatic device_method_t mpt_methods[] = { 158101704Smjacob /* Device interface */ 159147883Sscottl DEVMETHOD(device_probe, mpt_pci_probe), 160147883Sscottl DEVMETHOD(device_attach, mpt_pci_attach), 161147883Sscottl DEVMETHOD(device_detach, mpt_pci_detach), 162147883Sscottl DEVMETHOD(device_shutdown, mpt_pci_shutdown), 163233403Smarius DEVMETHOD_END 164101704Smjacob}; 165101704Smjacob 166101704Smjacobstatic driver_t mpt_driver = { 167147883Sscottl "mpt", mpt_methods, sizeof(struct mpt_softc) 168101704Smjacob}; 169260058Smarius 170101704Smjacobstatic devclass_t mpt_devclass; 171233403SmariusDRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, NULL, NULL); 172165058SmjacobMODULE_DEPEND(mpt, pci, 1, 1, 1); 173101704SmjacobMODULE_VERSION(mpt, 1); 174101704Smjacob 175101704Smjacobstatic int 176147883Sscottlmpt_pci_probe(device_t dev) 177101704Smjacob{ 178233403Smarius const char *desc; 179233886Smarius int rval; 180101704Smjacob 181233403Smarius if (pci_get_vendor(dev) != MPI_MANUFACTPAGE_VENDORID_LSILOGIC) 182101704Smjacob return (ENXIO); 183101704Smjacob 184233886Smarius rval = BUS_PROBE_DEFAULT; 185232411Sken switch (pci_get_device(dev)) { 186233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC909_FB: 187101704Smjacob desc = "LSILogic FC909 FC Adapter"; 188101704Smjacob break; 189233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC909: 190102596Smjacob desc = "LSILogic FC909A FC Adapter"; 191102596Smjacob break; 192233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919: 193103829Smjacob desc = "LSILogic FC919 FC Adapter"; 194103829Smjacob break; 195233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB: 196232411Sken desc = "LSILogic FC919 LAN Adapter"; 197232411Sken break; 198233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929: 199162140Smjacob desc = "Dual LSILogic FC929 FC Adapter"; 200101704Smjacob break; 201233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB: 202232411Sken desc = "Dual LSILogic FC929 LAN Adapter"; 203232411Sken break; 204233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919X: 205162140Smjacob desc = "LSILogic FC919 FC PCI-X Adapter"; 206159494Smjacob break; 207233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB: 208232411Sken desc = "LSILogic FC919 LAN PCI-X Adapter"; 209232411Sken break; 210233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929X: 211162140Smjacob desc = "Dual LSILogic FC929X 2Gb/s FC PCI-X Adapter"; 212150007Smjacob break; 213233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB: 214232411Sken desc = "Dual LSILogic FC929X LAN PCI-X Adapter"; 215232411Sken break; 216233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949E: 217162140Smjacob desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-Express Adapter"; 218162140Smjacob break; 219233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949X: 220162140Smjacob desc = "Dual LSILogic FC7X04X 4Gb/s FC PCI-X Adapter"; 221158279Smjacob break; 222233403Smarius case MPI_MANUFACTPAGE_DEVID_53C1030: 223233403Smarius case MPI_MANUFACTPAGE_DEVID_53C1030ZC: 224101704Smjacob desc = "LSILogic 1030 Ultra4 Adapter"; 225101704Smjacob break; 226233886Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB: 227233886Smarius /* 228233886Smarius * Allow mfi(4) to claim this device in case it's in MegaRAID 229233886Smarius * mode. 230233886Smarius */ 231233886Smarius rval = BUS_PROBE_LOW_PRIORITY; 232233886Smarius /* FALLTHROUGH */ 233233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064: 234233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064A: 235233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064E: 236233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1066: 237233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1066E: 238233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068: 239233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB: 240233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068E: 241233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1078: 242233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB: 243162140Smjacob desc = "LSILogic SAS/SATA Adapter"; 244155521Smjacob break; 245101704Smjacob default: 246101704Smjacob return (ENXIO); 247101704Smjacob } 248101704Smjacob 249101704Smjacob device_set_desc(dev, desc); 250233886Smarius return (rval); 251101704Smjacob} 252101704Smjacob 253101704Smjacobstatic void 254147883Sscottlmpt_set_options(struct mpt_softc *mpt) 255101704Smjacob{ 256101704Smjacob int tval; 257101704Smjacob 258101704Smjacob tval = 0; 259101704Smjacob if (resource_int_value(device_get_name(mpt->dev), 260101704Smjacob device_get_unit(mpt->dev), "debug", &tval) == 0 && tval != 0) { 261159041Smjacob mpt->verbose = tval; 262101704Smjacob } 263160290Smjacob tval = -1; 264157117Smjacob if (resource_int_value(device_get_name(mpt->dev), 265160290Smjacob device_get_unit(mpt->dev), "role", &tval) == 0 && tval >= 0 && 266157117Smjacob tval <= 3) { 267160290Smjacob mpt->cfg_role = tval; 268160290Smjacob mpt->do_cfg_role = 1; 269157117Smjacob } 270164416Smjacob tval = 0; 271164417Smjacob mpt->msi_enable = 0; 272223985Smarius if (mpt->is_sas) 273223985Smarius mpt->msi_enable = 1; 274164416Smjacob if (resource_int_value(device_get_name(mpt->dev), 275223985Smarius device_get_unit(mpt->dev), "msi_enable", &tval) == 0) { 276223985Smarius mpt->msi_enable = tval; 277164416Smjacob } 278101704Smjacob} 279101704Smjacob 280260058Smarius#if 0 281102303Smjacobstatic void 282147883Sscottlmpt_link_peer(struct mpt_softc *mpt) 283102303Smjacob{ 284147883Sscottl struct mpt_softc *mpt2; 285102303Smjacob 286157662Smjacob if (mpt->unit == 0) { 287102303Smjacob return; 288157662Smjacob } 289102303Smjacob /* 290102303Smjacob * XXX: depends on probe order 291102303Smjacob */ 292147883Sscottl mpt2 = (struct mpt_softc *)devclass_get_softc(mpt_devclass,mpt->unit-1); 293102303Smjacob 294102303Smjacob if (mpt2 == NULL) { 295102303Smjacob return; 296102303Smjacob } 297102303Smjacob if (pci_get_vendor(mpt2->dev) != pci_get_vendor(mpt->dev)) { 298102303Smjacob return; 299102303Smjacob } 300102303Smjacob if (pci_get_device(mpt2->dev) != pci_get_device(mpt->dev)) { 301102303Smjacob return; 302102303Smjacob } 303102303Smjacob mpt->mpt2 = mpt2; 304102303Smjacob mpt2->mpt2 = mpt; 305147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 306147883Sscottl mpt_prt(mpt, "linking with peer (mpt%d)\n", 307102303Smjacob device_get_unit(mpt2->dev)); 308102303Smjacob } 309102303Smjacob} 310102303Smjacob 311157662Smjacobstatic void 312157662Smjacobmpt_unlink_peer(struct mpt_softc *mpt) 313157662Smjacob{ 314224493Smarius 315157662Smjacob if (mpt->mpt2) { 316157662Smjacob mpt->mpt2->mpt2 = NULL; 317157662Smjacob } 318157662Smjacob} 319260058Smarius#endif 320102303Smjacob 321101704Smjacobstatic int 322147883Sscottlmpt_pci_attach(device_t dev) 323101704Smjacob{ 324147883Sscottl struct mpt_softc *mpt; 325147883Sscottl int iqd; 326260058Smarius uint32_t val; 327210943Smjacob int mpt_io_bar, mpt_mem_bar; 328101704Smjacob 329147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 330233403Smarius 331232411Sken switch (pci_get_device(dev)) { 332233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC909_FB: 333233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC909: 334233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919: 335233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919_LAN_FB: 336233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929: 337233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB: 338233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929X: 339233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929X_LAN_FB: 340233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919X: 341233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC919X_LAN_FB: 342233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949E: 343233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949X: 344101704Smjacob mpt->is_fc = 1; 345101704Smjacob break; 346233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1078: 347233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1078DE_FB: 348231518Smarius mpt->is_1078 = 1; 349231518Smarius /* FALLTHROUGH */ 350233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064: 351233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064A: 352233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1064E: 353233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1066: 354233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1066E: 355233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068: 356233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068A_FB: 357233403Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068E: 358233827Smarius case MPI_MANUFACTPAGE_DEVID_SAS1068E_FB: 359155521Smjacob mpt->is_sas = 1; 360155521Smjacob break; 361101704Smjacob default: 362159178Smjacob mpt->is_spi = 1; 363101704Smjacob break; 364101704Smjacob } 365101704Smjacob mpt->dev = dev; 366101704Smjacob mpt->unit = device_get_unit(dev); 367147883Sscottl mpt->raid_resync_rate = MPT_RAID_RESYNC_RATE_DEFAULT; 368147883Sscottl mpt->raid_mwce_setting = MPT_RAID_MWCE_DEFAULT; 369147883Sscottl mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; 370155521Smjacob mpt->verbose = MPT_PRT_NONE; 371157662Smjacob mpt->role = MPT_ROLE_NONE; 372207287Smarius mpt->mpt_ini_id = MPT_INI_ID_NONE; 373207287Smarius#ifdef __sparc64__ 374207287Smarius if (mpt->is_spi) 375207287Smarius mpt->mpt_ini_id = OF_getscsinitid(dev); 376207287Smarius#endif 377101704Smjacob mpt_set_options(mpt); 378155521Smjacob if (mpt->verbose == MPT_PRT_NONE) { 379155521Smjacob mpt->verbose = MPT_PRT_WARN; 380155521Smjacob /* Print INFO level (if any) if bootverbose is set */ 381155521Smjacob mpt->verbose += (bootverbose != 0)? 1 : 0; 382155521Smjacob } 383101704Smjacob 384101704Smjacob /* 385101704Smjacob * Make sure that SERR, PERR, WRITE INVALIDATE and BUSMASTER are set. 386101704Smjacob */ 387260058Smarius val = pci_read_config(dev, PCIR_COMMAND, 2); 388260058Smarius val |= PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN | 389101704Smjacob PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 390260058Smarius pci_write_config(dev, PCIR_COMMAND, val, 2); 391101704Smjacob 392101704Smjacob /* 393101704Smjacob * Make sure we've disabled the ROM. 394101704Smjacob */ 395260058Smarius val = pci_read_config(dev, PCIR_BIOS, 4); 396260058Smarius val &= ~PCIM_BIOS_ENABLE; 397260058Smarius pci_write_config(dev, PCIR_BIOS, val, 4); 398101704Smjacob 399260058Smarius#if 0 400102303Smjacob /* 401102303Smjacob * Is this part a dual? 402102303Smjacob * If so, link with our partner (around yet) 403102303Smjacob */ 404232411Sken switch (pci_get_device(dev)) { 405233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929: 406233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC929_LAN_FB: 407233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949E: 408233403Smarius case MPI_MANUFACTPAGE_DEVICEID_FC949X: 409233403Smarius case MPI_MANUFACTPAGE_DEVID_53C1030: 410233403Smarius case MPI_MANUFACTPAGE_DEVID_53C1030ZC: 411102303Smjacob mpt_link_peer(mpt); 412232411Sken break; 413232411Sken default: 414232411Sken break; 415101704Smjacob } 416260058Smarius#endif 417101704Smjacob 418147883Sscottl /* 419210943Smjacob * Figure out which are the I/O and MEM Bars 420210943Smjacob */ 421260058Smarius val = pci_read_config(dev, PCIR_BAR(0), 4); 422260058Smarius if (PCI_BAR_IO(val)) { 423210943Smjacob /* BAR0 is IO, BAR1 is memory */ 424210943Smjacob mpt_io_bar = 0; 425210943Smjacob mpt_mem_bar = 1; 426210943Smjacob } else { 427210943Smjacob /* BAR0 is memory, BAR1 is IO */ 428210943Smjacob mpt_mem_bar = 0; 429210943Smjacob mpt_io_bar = 1; 430210943Smjacob } 431210943Smjacob 432210943Smjacob /* 433147883Sscottl * Set up register access. PIO mode is required for 434155521Smjacob * certain reset operations (but must be disabled for 435155521Smjacob * some cards otherwise). 436147883Sscottl */ 437223985Smarius mpt_io_bar = PCIR_BAR(mpt_io_bar); 438216764Sjhb mpt->pci_pio_reg = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 439223985Smarius &mpt_io_bar, RF_ACTIVE); 440147883Sscottl if (mpt->pci_pio_reg == NULL) { 441231518Smarius if (bootverbose) { 442231518Smarius device_printf(dev, 443231518Smarius "unable to map registers in PIO mode\n"); 444231518Smarius } 445231518Smarius } else { 446231518Smarius mpt->pci_pio_st = rman_get_bustag(mpt->pci_pio_reg); 447231518Smarius mpt->pci_pio_sh = rman_get_bushandle(mpt->pci_pio_reg); 448147883Sscottl } 449147883Sscottl 450223985Smarius mpt_mem_bar = PCIR_BAR(mpt_mem_bar); 451216764Sjhb mpt->pci_reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 452223985Smarius &mpt_mem_bar, RF_ACTIVE); 453101704Smjacob if (mpt->pci_reg == NULL) { 454231518Smarius if (bootverbose || mpt->is_sas || mpt->pci_pio_reg == NULL) { 455231518Smarius device_printf(dev, 456231518Smarius "Unable to memory map registers.\n"); 457231518Smarius } 458231518Smarius if (mpt->is_sas || mpt->pci_pio_reg == NULL) { 459155521Smjacob device_printf(dev, "Giving Up.\n"); 460155521Smjacob goto bad; 461155521Smjacob } 462231518Smarius if (bootverbose) { 463231518Smarius device_printf(dev, "Falling back to PIO mode.\n"); 464231518Smarius } 465147883Sscottl mpt->pci_st = mpt->pci_pio_st; 466147883Sscottl mpt->pci_sh = mpt->pci_pio_sh; 467147883Sscottl } else { 468147883Sscottl mpt->pci_st = rman_get_bustag(mpt->pci_reg); 469147883Sscottl mpt->pci_sh = rman_get_bushandle(mpt->pci_reg); 470101704Smjacob } 471101704Smjacob 472101704Smjacob /* Get a handle to the interrupt */ 473101704Smjacob iqd = 0; 474166721Sjhb if (mpt->msi_enable) { 475166721Sjhb /* 476166721Sjhb * First try to alloc an MSI-X message. If that 477166721Sjhb * fails, then try to alloc an MSI message instead. 478166721Sjhb */ 479260058Smarius val = 1; 480260058Smarius if (pci_alloc_msix(dev, &val) == 0) 481260058Smarius iqd = 1; 482260058Smarius val = 1; 483260058Smarius if (iqd == 0 && pci_alloc_msi(dev, &val) == 0) 484260058Smarius iqd = 1; 485166721Sjhb } 486127135Snjl mpt->pci_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, 487260058Smarius RF_ACTIVE | (iqd != 0 ? 0 : RF_SHAREABLE)); 488101704Smjacob if (mpt->pci_irq == NULL) { 489101704Smjacob device_printf(dev, "could not allocate interrupt\n"); 490101704Smjacob goto bad; 491101704Smjacob } 492101704Smjacob 493147883Sscottl MPT_LOCK_SETUP(mpt); 494147883Sscottl 495147883Sscottl /* Disable interrupts at the part */ 496147883Sscottl mpt_disable_ints(mpt); 497147883Sscottl 498101704Smjacob /* Register the interrupt handler */ 499260058Smarius if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, NULL, mpt_pci_intr, 500101704Smjacob mpt, &mpt->ih)) { 501101704Smjacob device_printf(dev, "could not setup interrupt\n"); 502101704Smjacob goto bad; 503101704Smjacob } 504101704Smjacob 505101704Smjacob /* Allocate dma memory */ 506101704Smjacob if (mpt_dma_mem_alloc(mpt)) { 507159091Smjacob mpt_prt(mpt, "Could not allocate DMA memory\n"); 508101704Smjacob goto bad; 509101704Smjacob } 510101704Smjacob 511233403Smarius#if 0 512102199Smjacob /* 513102199Smjacob * Save the PCI config register values 514102199Smjacob * 515102199Smjacob * Hard resets are known to screw up the BAR for diagnostic 516102199Smjacob * memory accesses (Mem1). 517102199Smjacob * 518102199Smjacob * Using Mem1 is known to make the chip stop responding to 519102199Smjacob * configuration space transfers, so we need to save it now 520102199Smjacob */ 521101704Smjacob 522101704Smjacob mpt_read_config_regs(mpt); 523233403Smarius#endif 524101704Smjacob 525155521Smjacob /* 526155521Smjacob * Disable PIO until we need it 527155521Smjacob */ 528159919Smjacob if (mpt->is_sas) { 529159919Smjacob pci_disable_io(dev, SYS_RES_IOPORT); 530159919Smjacob } 531155521Smjacob 532101704Smjacob /* Initialize the hardware */ 533101704Smjacob if (mpt->disabled == 0) { 534147883Sscottl if (mpt_attach(mpt) != 0) { 535101704Smjacob goto bad; 536102199Smjacob } 537157117Smjacob } else { 538157117Smjacob mpt_prt(mpt, "device disabled at user request\n"); 539157117Smjacob goto bad; 540101704Smjacob } 541101704Smjacob 542157117Smjacob mpt->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, mpt_pci_shutdown, 543249849Smav dev, SHUTDOWN_PRI_LAST); 544157117Smjacob 545157117Smjacob if (mpt->eh == NULL) { 546157117Smjacob mpt_prt(mpt, "shutdown event registration failed\n"); 547260058Smarius mpt_disable_ints(mpt); 548157117Smjacob (void) mpt_detach(mpt); 549260058Smarius mpt_reset(mpt, /*reinit*/FALSE); 550260058Smarius mpt_raid_free_mem(mpt); 551157117Smjacob goto bad; 552157117Smjacob } 553101704Smjacob return (0); 554101704Smjacob 555101704Smjacobbad: 556101704Smjacob mpt_dma_mem_free(mpt); 557101704Smjacob mpt_free_bus_resources(mpt); 558260058Smarius#if 0 559157662Smjacob mpt_unlink_peer(mpt); 560260058Smarius#endif 561101704Smjacob 562157662Smjacob MPT_LOCK_DESTROY(mpt); 563157662Smjacob 564101704Smjacob /* 565101704Smjacob * but return zero to preserve unit numbering 566101704Smjacob */ 567101704Smjacob return (0); 568101704Smjacob} 569101704Smjacob 570102199Smjacob/* 571101704Smjacob * Free bus resources 572101704Smjacob */ 573101704Smjacobstatic void 574147883Sscottlmpt_free_bus_resources(struct mpt_softc *mpt) 575101704Smjacob{ 576224493Smarius 577101704Smjacob if (mpt->ih) { 578101704Smjacob bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih); 579223985Smarius mpt->ih = NULL; 580101704Smjacob } 581101704Smjacob 582101704Smjacob if (mpt->pci_irq) { 583164305Sjhb bus_release_resource(mpt->dev, SYS_RES_IRQ, 584223985Smarius rman_get_rid(mpt->pci_irq), mpt->pci_irq); 585260058Smarius pci_release_msi(mpt->dev); 586223985Smarius mpt->pci_irq = NULL; 587101704Smjacob } 588101704Smjacob 589147883Sscottl if (mpt->pci_pio_reg) { 590223985Smarius bus_release_resource(mpt->dev, SYS_RES_IOPORT, 591223985Smarius rman_get_rid(mpt->pci_pio_reg), mpt->pci_pio_reg); 592223985Smarius mpt->pci_pio_reg = NULL; 593147883Sscottl } 594260058Smarius 595101704Smjacob if (mpt->pci_reg) { 596223985Smarius bus_release_resource(mpt->dev, SYS_RES_MEMORY, 597223985Smarius rman_get_rid(mpt->pci_reg), mpt->pci_reg); 598223985Smarius mpt->pci_reg = NULL; 599101704Smjacob } 600101704Smjacob} 601101704Smjacob 602102199Smjacob/* 603101704Smjacob * Disconnect ourselves from the system. 604101704Smjacob */ 605101704Smjacobstatic int 606147883Sscottlmpt_pci_detach(device_t dev) 607101704Smjacob{ 608147883Sscottl struct mpt_softc *mpt; 609101704Smjacob 610147883Sscottl mpt = (struct mpt_softc*)device_get_softc(dev); 611101704Smjacob 612101704Smjacob if (mpt) { 613101704Smjacob mpt_disable_ints(mpt); 614147883Sscottl mpt_detach(mpt); 615147883Sscottl mpt_reset(mpt, /*reinit*/FALSE); 616260058Smarius mpt_raid_free_mem(mpt); 617101704Smjacob mpt_dma_mem_free(mpt); 618101704Smjacob mpt_free_bus_resources(mpt); 619260058Smarius#if 0 620260058Smarius mpt_unlink_peer(mpt); 621260058Smarius#endif 622158982Smjacob if (mpt->eh != NULL) { 623180152Sjhb EVENTHANDLER_DEREGISTER(shutdown_post_sync, mpt->eh); 624147883Sscottl } 625260058Smarius MPT_LOCK_DESTROY(mpt); 626101704Smjacob } 627101704Smjacob return(0); 628101704Smjacob} 629101704Smjacob 630102199Smjacob/* 631101704Smjacob * Disable the hardware 632101704Smjacob */ 633101704Smjacobstatic int 634147883Sscottlmpt_pci_shutdown(device_t dev) 635101704Smjacob{ 636147883Sscottl struct mpt_softc *mpt; 637101704Smjacob 638147883Sscottl mpt = (struct mpt_softc *)device_get_softc(dev); 639260058Smarius if (mpt) 640260058Smarius return (mpt_shutdown(mpt)); 641101704Smjacob return(0); 642101704Smjacob} 643101704Smjacob 644101704Smjacobstatic int 645147883Sscottlmpt_dma_mem_alloc(struct mpt_softc *mpt) 646101704Smjacob{ 647103871Smjacob size_t len; 648147883Sscottl struct mpt_map_info mi; 649101704Smjacob 650101704Smjacob /* Check if we alreay have allocated the reply memory */ 651123740Speter if (mpt->reply_phys != 0) { 652101704Smjacob return 0; 653103871Smjacob } 654101704Smjacob 655147883Sscottl len = sizeof (request_t) * MPT_MAX_REQUESTS(mpt); 656147883Sscottl mpt->request_pool = (request_t *)malloc(len, M_DEVBUF, M_WAITOK|M_ZERO); 657103871Smjacob 658101704Smjacob /* 659155521Smjacob * Create a parent dma tag for this device. 660101704Smjacob * 661159091Smjacob * Align at byte boundaries, 662159091Smjacob * Limit to 32-bit addressing for request/reply queues. 663101704Smjacob */ 664164314Sjb if (mpt_dma_tag_create(mpt, /*parent*/bus_get_dma_tag(mpt->dev), 665164314Sjb /*alignment*/1, /*boundary*/0, /*lowaddr*/BUS_SPACE_MAXADDR, 666147883Sscottl /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, 667147883Sscottl /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 668209961Smarius /*nsegments*/BUS_SPACE_UNRESTRICTED, 669209961Smarius /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, /*flags*/0, 670147883Sscottl &mpt->parent_dmat) != 0) { 671159091Smjacob mpt_prt(mpt, "cannot create parent dma tag\n"); 672101704Smjacob return (1); 673101704Smjacob } 674101704Smjacob 675101704Smjacob /* Create a child tag for reply buffers */ 676159091Smjacob if (mpt_dma_tag_create(mpt, mpt->parent_dmat, PAGE_SIZE, 0, 677159091Smjacob BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, 678155521Smjacob NULL, NULL, 2 * PAGE_SIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 0, 679147883Sscottl &mpt->reply_dmat) != 0) { 680159091Smjacob mpt_prt(mpt, "cannot create a dma tag for replies\n"); 681101704Smjacob return (1); 682101704Smjacob } 683101704Smjacob 684220945Smarius /* Allocate some DMA accessible memory for replies */ 685101704Smjacob if (bus_dmamem_alloc(mpt->reply_dmat, (void **)&mpt->reply, 686101704Smjacob BUS_DMA_NOWAIT, &mpt->reply_dmap) != 0) { 687159091Smjacob mpt_prt(mpt, "cannot allocate %lu bytes of reply memory\n", 688155521Smjacob (u_long) (2 * PAGE_SIZE)); 689101704Smjacob return (1); 690101704Smjacob } 691101704Smjacob 692147883Sscottl mi.mpt = mpt; 693147883Sscottl mi.error = 0; 694101704Smjacob 695101704Smjacob /* Load and lock it into "bus space" */ 696101704Smjacob bus_dmamap_load(mpt->reply_dmat, mpt->reply_dmap, mpt->reply, 697155521Smjacob 2 * PAGE_SIZE, mpt_map_rquest, &mi, 0); 698101704Smjacob 699147883Sscottl if (mi.error) { 700159091Smjacob mpt_prt(mpt, "error %d loading dma map for DMA reply queue\n", 701159091Smjacob mi.error); 702101704Smjacob return (1); 703101704Smjacob } 704147883Sscottl mpt->reply_phys = mi.phys; 705101704Smjacob 706101704Smjacob return (0); 707101704Smjacob} 708101704Smjacob 709101704Smjacob/* Deallocate memory that was allocated by mpt_dma_mem_alloc 710101704Smjacob */ 711101704Smjacobstatic void 712147883Sscottlmpt_dma_mem_free(struct mpt_softc *mpt) 713101704Smjacob{ 714101704Smjacob 715101704Smjacob /* Make sure we aren't double destroying */ 716101704Smjacob if (mpt->reply_dmat == 0) { 717159091Smjacob mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n"); 718101704Smjacob return; 719101704Smjacob } 720101704Smjacob 721101704Smjacob bus_dmamap_unload(mpt->reply_dmat, mpt->reply_dmap); 722101704Smjacob bus_dmamem_free(mpt->reply_dmat, mpt->reply, mpt->reply_dmap); 723101704Smjacob bus_dma_tag_destroy(mpt->reply_dmat); 724101704Smjacob bus_dma_tag_destroy(mpt->parent_dmat); 725223985Smarius mpt->reply_dmat = NULL; 726103871Smjacob free(mpt->request_pool, M_DEVBUF); 727223985Smarius mpt->request_pool = NULL; 728101704Smjacob} 729101704Smjacob 730233403Smarius#if 0 731101704Smjacob/* Reads modifiable (via PCI transactions) config registers */ 732101704Smjacobstatic void 733147883Sscottlmpt_read_config_regs(struct mpt_softc *mpt) 734101704Smjacob{ 735224493Smarius 736101704Smjacob mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2); 737101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize = 738101704Smjacob pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2); 739119690Sjhb mpt->pci_cfg.IO_BAR = pci_read_config(mpt->dev, PCIR_BAR(0), 4); 740119690Sjhb mpt->pci_cfg.Mem0_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(1), 4); 741119690Sjhb mpt->pci_cfg.Mem0_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(2), 4); 742119690Sjhb mpt->pci_cfg.Mem1_BAR[0] = pci_read_config(mpt->dev, PCIR_BAR(3), 4); 743119690Sjhb mpt->pci_cfg.Mem1_BAR[1] = pci_read_config(mpt->dev, PCIR_BAR(4), 4); 744101704Smjacob mpt->pci_cfg.ROM_BAR = pci_read_config(mpt->dev, PCIR_BIOS, 4); 745101704Smjacob mpt->pci_cfg.IntLine = pci_read_config(mpt->dev, PCIR_INTLINE, 1); 746101704Smjacob mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4); 747101704Smjacob} 748101704Smjacob 749101704Smjacob/* Sets modifiable config registers */ 750224493Smariusstatic void 751147883Sscottlmpt_set_config_regs(struct mpt_softc *mpt) 752101704Smjacob{ 753147883Sscottl uint32_t val; 754101704Smjacob 755101704Smjacob#define MPT_CHECK(reg, offset, size) \ 756101704Smjacob val = pci_read_config(mpt->dev, offset, size); \ 757101704Smjacob if (mpt->pci_cfg.reg != val) { \ 758103914Smjacob mpt_prt(mpt, \ 759101704Smjacob "Restoring " #reg " to 0x%X from 0x%X\n", \ 760101704Smjacob mpt->pci_cfg.reg, val); \ 761101704Smjacob } 762101704Smjacob 763147883Sscottl if (mpt->verbose >= MPT_PRT_DEBUG) { 764101704Smjacob MPT_CHECK(Command, PCIR_COMMAND, 2); 765101704Smjacob MPT_CHECK(LatencyTimer_LineSize, PCIR_CACHELNSZ, 2); 766119690Sjhb MPT_CHECK(IO_BAR, PCIR_BAR(0), 4); 767119690Sjhb MPT_CHECK(Mem0_BAR[0], PCIR_BAR(1), 4); 768119690Sjhb MPT_CHECK(Mem0_BAR[1], PCIR_BAR(2), 4); 769119690Sjhb MPT_CHECK(Mem1_BAR[0], PCIR_BAR(3), 4); 770119690Sjhb MPT_CHECK(Mem1_BAR[1], PCIR_BAR(4), 4); 771101704Smjacob MPT_CHECK(ROM_BAR, PCIR_BIOS, 4); 772101704Smjacob MPT_CHECK(IntLine, PCIR_INTLINE, 1); 773101704Smjacob MPT_CHECK(PMCSR, 0x44, 4); 774101704Smjacob } 775101704Smjacob#undef MPT_CHECK 776101704Smjacob 777101704Smjacob pci_write_config(mpt->dev, PCIR_COMMAND, mpt->pci_cfg.Command, 2); 778101704Smjacob pci_write_config(mpt->dev, PCIR_CACHELNSZ, 779101704Smjacob mpt->pci_cfg.LatencyTimer_LineSize, 2); 780119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(0), mpt->pci_cfg.IO_BAR, 4); 781119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(1), mpt->pci_cfg.Mem0_BAR[0], 4); 782119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(2), mpt->pci_cfg.Mem0_BAR[1], 4); 783119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(3), mpt->pci_cfg.Mem1_BAR[0], 4); 784119690Sjhb pci_write_config(mpt->dev, PCIR_BAR(4), mpt->pci_cfg.Mem1_BAR[1], 4); 785101704Smjacob pci_write_config(mpt->dev, PCIR_BIOS, mpt->pci_cfg.ROM_BAR, 4); 786101704Smjacob pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1); 787101704Smjacob pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4); 788101704Smjacob} 789224493Smarius#endif 790102199Smjacob 791102199Smjacobstatic void 792102199Smjacobmpt_pci_intr(void *arg) 793102199Smjacob{ 794147883Sscottl struct mpt_softc *mpt; 795147883Sscottl 796147883Sscottl mpt = (struct mpt_softc *)arg; 797102199Smjacob MPT_LOCK(mpt); 798147883Sscottl mpt_intr(mpt); 799102199Smjacob MPT_UNLOCK(mpt); 800102199Smjacob} 801