11e66f787SSean Bruno /*- 29fac68fcSPAPANI SRIKANTH * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. 31e66f787SSean Bruno * 41e66f787SSean Bruno * Redistribution and use in source and binary forms, with or without 51e66f787SSean Bruno * modification, are permitted provided that the following conditions 61e66f787SSean Bruno * are met: 71e66f787SSean Bruno * 1. Redistributions of source code must retain the above copyright 81e66f787SSean Bruno * notice, this list of conditions and the following disclaimer. 91e66f787SSean Bruno * 2. Redistributions in binary form must reproduce the above copyright 101e66f787SSean Bruno * notice, this list of conditions and the following disclaimer in the 111e66f787SSean Bruno * documentation and/or other materials provided with the distribution. 121e66f787SSean Bruno * 131e66f787SSean Bruno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 141e66f787SSean Bruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 151e66f787SSean Bruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161e66f787SSean Bruno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 171e66f787SSean Bruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 181e66f787SSean Bruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 191e66f787SSean Bruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 201e66f787SSean Bruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 211e66f787SSean Bruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 221e66f787SSean Bruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 231e66f787SSean Bruno * SUCH DAMAGE. 241e66f787SSean Bruno */ 251e66f787SSean Bruno 261e66f787SSean Bruno /* $FreeBSD$ */ 271e66f787SSean Bruno 281e66f787SSean Bruno /* 291e66f787SSean Bruno * Driver for the Microsemi Smart storage controllers 301e66f787SSean Bruno */ 311e66f787SSean Bruno 321e66f787SSean Bruno #include "smartpqi_includes.h" 331e66f787SSean Bruno #include "smartpqi_prototypes.h" 341e66f787SSean Bruno 359fac68fcSPAPANI SRIKANTH CTASSERT(BSD_SUCCESS == PQI_STATUS_SUCCESS); 369fac68fcSPAPANI SRIKANTH 371e66f787SSean Bruno /* 381e66f787SSean Bruno * Supported devices 391e66f787SSean Bruno */ 401e66f787SSean Bruno struct pqi_ident 411e66f787SSean Bruno { 421e66f787SSean Bruno u_int16_t vendor; 431e66f787SSean Bruno u_int16_t device; 441e66f787SSean Bruno u_int16_t subvendor; 451e66f787SSean Bruno u_int16_t subdevice; 461e66f787SSean Bruno int hwif; 471e66f787SSean Bruno char *desc; 481e66f787SSean Bruno } pqi_identifiers[] = { 491e66f787SSean Bruno /* (MSCC PM8205 8x12G based) */ 501e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x600, PQI_HWIF_SRCV, "P408i-p SR Gen10"}, 511e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x601, PQI_HWIF_SRCV, "P408e-p SR Gen10"}, 521e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x602, PQI_HWIF_SRCV, "P408i-a SR Gen10"}, 531e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x603, PQI_HWIF_SRCV, "P408i-c SR Gen10"}, 541e66f787SSean Bruno {0x9005, 0x028f, 0x1028, 0x1FE0, PQI_HWIF_SRCV, "SmartRAID 3162-8i/eDell"}, 551e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x608, PQI_HWIF_SRCV, "SmartRAID 3162-8i/e"}, 561e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x609, PQI_HWIF_SRCV, "P408i-sb SR G10"}, 571e66f787SSean Bruno 581e66f787SSean Bruno /* (MSCC PM8225 8x12G based) */ 591e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x650, PQI_HWIF_SRCV, "E208i-p SR Gen10"}, 601e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x651, PQI_HWIF_SRCV, "E208e-p SR Gen10"}, 611e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x652, PQI_HWIF_SRCV, "E208i-c SR Gen10"}, 621e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x654, PQI_HWIF_SRCV, "E208i-a SR Gen10"}, 631e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x655, PQI_HWIF_SRCV, "P408e-m SR Gen10"}, 641e66f787SSean Bruno 651e66f787SSean Bruno /* (MSCC PM8221 8x12G based) */ 661e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x700, PQI_HWIF_SRCV, "P204i-c SR Gen10"}, 671e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x701, PQI_HWIF_SRCV, "P204i-b SR Gen10"}, 689fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0x1104, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-2GB"}, 699fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0x1106, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-1GB"}, 709fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0x1108, PQI_HWIF_SRCV, "UN RAID P4408-Ma-8i-2GB"}, 719fac68fcSPAPANI SRIKANTH 721e66f787SSean Bruno 731e66f787SSean Bruno /* (MSCC PM8204 8x12G based) */ 741e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x800, PQI_HWIF_SRCV, "SmartRAID 3154-8i"}, 751e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x801, PQI_HWIF_SRCV, "SmartRAID 3152-8i"}, 761e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x802, PQI_HWIF_SRCV, "SmartRAID 3151-4i"}, 771e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x803, PQI_HWIF_SRCV, "SmartRAID 3101-4i"}, 781e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x804, PQI_HWIF_SRCV, "SmartRAID 3154-8e"}, 791e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x805, PQI_HWIF_SRCV, "SmartRAID 3102-8i"}, 801e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x806, PQI_HWIF_SRCV, "SmartRAID 3100"}, 811e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x807, PQI_HWIF_SRCV, "SmartRAID 3162-8i"}, 821e66f787SSean Bruno {0x9005, 0x028f, 0x152d, 0x8a22, PQI_HWIF_SRCV, "QS-8204-8i"}, 83b17f4335SSean Bruno {0x9005, 0x028f, 0x193d, 0xf460, PQI_HWIF_SRCV, "UN RAID P460-M4"}, 84b17f4335SSean Bruno {0x9005, 0x028f, 0x193d, 0xf461, PQI_HWIF_SRCV, "UN RAID P460-B4"}, 859fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1bd4, 0x004b, PQI_HWIF_SRCV, "INSPUR PM8204-2GB"}, 869fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1bd4, 0x004c, PQI_HWIF_SRCV, "INSPUR PM8204-4GB"}, 879fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0x1105, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-2GB"}, 889fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0x1107, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-4GB"}, 899fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1d8d, 0x800, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8204-8i"}, 909fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x9005, 0x0808, PQI_HWIF_SRCV, "SmartRAID 3101E-4i"}, 919fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x9005, 0x0809, PQI_HWIF_SRCV, "SmartRAID 3102E-8i"}, 929fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x9005, 0x080a, PQI_HWIF_SRCV, "SmartRAID 3152-8i/N"}, 931e66f787SSean Bruno 941e66f787SSean Bruno /* (MSCC PM8222 8x12G based) */ 951e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x900, PQI_HWIF_SRCV, "SmartHBA 2100-8i"}, 961e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x901, PQI_HWIF_SRCV, "SmartHBA 2100-4i"}, 971e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x902, PQI_HWIF_SRCV, "HBA 1100-8i"}, 981e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x903, PQI_HWIF_SRCV, "HBA 1100-4i"}, 991e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x904, PQI_HWIF_SRCV, "SmartHBA 2100-8e"}, 1001e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x905, PQI_HWIF_SRCV, "HBA 1100-8e"}, 1011e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x906, PQI_HWIF_SRCV, "SmartHBA 2100-4i4e"}, 1021e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x907, PQI_HWIF_SRCV, "HBA 1100"}, 1031e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x908, PQI_HWIF_SRCV, "SmartHBA 2100"}, 1041e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x90a, PQI_HWIF_SRCV, "SmartHBA 2100A-8i"}, 105b17f4335SSean Bruno {0x9005, 0x028f, 0x193d, 0x8460, PQI_HWIF_SRCV, "UN HBA H460-M1"}, 106b17f4335SSean Bruno {0x9005, 0x028f, 0x193d, 0x8461, PQI_HWIF_SRCV, "UN HBA H460-B1"}, 1079fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0xc460, PQI_HWIF_SRCV, "UN RAID P460-M2"}, 1089fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x193d, 0xc461, PQI_HWIF_SRCV, "UN RAID P460-B2"}, 1099fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1bd4, 0x004a, PQI_HWIF_SRCV, "INSPUR PM8222-SHBA"}, 110b17f4335SSean Bruno {0x9005, 0x028f, 0x13fe, 0x8312, PQI_HWIF_SRCV, "MIC-8312BridgeB"}, 1119fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1bd4, 0x004f, PQI_HWIF_SRCV, "INSPUR PM8222-HBA"}, 1129fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1d8d, 0x908, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8222-8i"}, 1131e66f787SSean Bruno 1141e66f787SSean Bruno /* (SRCx MSCC FVB 24x12G based) */ 1151e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x1001, PQI_HWIF_SRCV, "MSCC FVB"}, 1161e66f787SSean Bruno 1171e66f787SSean Bruno /* (MSCC PM8241 24x12G based) */ 1181e66f787SSean Bruno 1191e66f787SSean Bruno /* (MSCC PM8242 24x12G based) */ 1201e66f787SSean Bruno {0x9005, 0x028f, 0x152d, 0x8a37, PQI_HWIF_SRCV, "QS-8242-24i"}, 1211e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1300, PQI_HWIF_SRCV, "HBA 1100-8i8e"}, 1221e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1301, PQI_HWIF_SRCV, "HBA 1100-24i"}, 1231e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1302, PQI_HWIF_SRCV, "SmartHBA 2100-8i8e"}, 1241e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1303, PQI_HWIF_SRCV, "SmartHBA 2100-24i"}, 125b17f4335SSean Bruno {0x9005, 0x028f, 0x105b, 0x1321, PQI_HWIF_SRCV, "8242-24i"}, 126b17f4335SSean Bruno {0x9005, 0x028f, 0x1bd4, 0x0045, PQI_HWIF_SRCV, "INSPUR SMART-HBA 8242-24i"}, 1271e66f787SSean Bruno 1281e66f787SSean Bruno /* (MSCC PM8236 16x12G based) */ 1291e66f787SSean Bruno {0x9005, 0x028f, 0x152d, 0x8a24, PQI_HWIF_SRCV, "QS-8236-16i"}, 1301e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1380, PQI_HWIF_SRCV, "SmartRAID 3154-16i"}, 131b17f4335SSean Bruno {0x9005, 0x028f, 0x1bd4, 0x0046, PQI_HWIF_SRCV, "INSPUR RAID 8236-16i"}, 1329fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1d8d, 0x806, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8236-16i"}, 1331e66f787SSean Bruno 1341e66f787SSean Bruno /* (MSCC PM8237 24x12G based) */ 1351e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x1100, PQI_HWIF_SRCV, "P816i-a SR Gen10"}, 1361e66f787SSean Bruno {0x9005, 0x028f, 0x103c, 0x1101, PQI_HWIF_SRCV, "P416ie-m SR G10"}, 1371e66f787SSean Bruno 1381e66f787SSean Bruno /* (MSCC PM8238 16x12G based) */ 1391e66f787SSean Bruno {0x9005, 0x028f, 0x152d, 0x8a23, PQI_HWIF_SRCV, "QS-8238-16i"}, 1401e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1280, PQI_HWIF_SRCV, "HBA 1100-16i"}, 1411e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1281, PQI_HWIF_SRCV, "HBA 1100-16e"}, 142b17f4335SSean Bruno {0x9005, 0x028f, 0x105b, 0x1211, PQI_HWIF_SRCV, "8238-16i"}, 143b17f4335SSean Bruno {0x9005, 0x028f, 0x1bd4, 0x0048, PQI_HWIF_SRCV, "INSPUR SMART-HBA 8238-16i"}, 144b17f4335SSean Bruno {0x9005, 0x028f, 0x9005, 0x1282, PQI_HWIF_SRCV, "SmartHBA 2100-16i"}, 1459fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1d8d, 0x916, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8238-16i"}, 1469fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x1458, 0x1000, PQI_HWIF_SRCV, "GIGABYTE SmartHBA CLN1832"}, 1471e66f787SSean Bruno 1481e66f787SSean Bruno /* (MSCC PM8240 24x12G based) */ 1491e66f787SSean Bruno {0x9005, 0x028f, 0x152d, 0x8a36, PQI_HWIF_SRCV, "QS-8240-24i"}, 1501e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1200, PQI_HWIF_SRCV, "SmartRAID 3154-24i"}, 1511e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1201, PQI_HWIF_SRCV, "SmartRAID 3154-8i16e"}, 1521e66f787SSean Bruno {0x9005, 0x028f, 0x9005, 0x1202, PQI_HWIF_SRCV, "SmartRAID 3154-8i8e"}, 153b17f4335SSean Bruno {0x9005, 0x028f, 0x1bd4, 0x0047, PQI_HWIF_SRCV, "INSPUR RAID 8240-24i"}, 1549fac68fcSPAPANI SRIKANTH 1559fac68fcSPAPANI SRIKANTH /* Huawei ID's */ 1569fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd227, PQI_HWIF_SRCV, "SR465C-M 4G"}, 1579fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd22a, PQI_HWIF_SRCV, "SR765-M"}, 1589fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd228, PQI_HWIF_SRCV, "SR455C-M 2G"}, 1599fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd22c, PQI_HWIF_SRCV, "SR455C-M 4G"}, 1609fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd229, PQI_HWIF_SRCV, "SR155-M"}, 1619fac68fcSPAPANI SRIKANTH {0x9005, 0x028f, 0x19e5, 0xd22b, PQI_HWIF_SRCV, "SR455C-ME 4G"}, 1629fac68fcSPAPANI SRIKANTH 1631e66f787SSean Bruno {0, 0, 0, 0, 0, 0} 1641e66f787SSean Bruno }; 1651e66f787SSean Bruno 1661e66f787SSean Bruno struct pqi_ident 1671e66f787SSean Bruno pqi_family_identifiers[] = { 1681e66f787SSean Bruno {0x9005, 0x028f, 0, 0, PQI_HWIF_SRCV, "Smart Array Storage Controller"}, 1691e66f787SSean Bruno {0, 0, 0, 0, 0, 0} 1701e66f787SSean Bruno }; 1711e66f787SSean Bruno 1721e66f787SSean Bruno /* 1731e66f787SSean Bruno * Function to identify the installed adapter. 1741e66f787SSean Bruno */ 1759fac68fcSPAPANI SRIKANTH static struct 1769fac68fcSPAPANI SRIKANTH pqi_ident *pqi_find_ident(device_t dev) 1771e66f787SSean Bruno { 1781e66f787SSean Bruno struct pqi_ident *m; 1791e66f787SSean Bruno u_int16_t vendid, devid, sub_vendid, sub_devid; 1801e66f787SSean Bruno 1811e66f787SSean Bruno vendid = pci_get_vendor(dev); 1821e66f787SSean Bruno devid = pci_get_device(dev); 1831e66f787SSean Bruno sub_vendid = pci_get_subvendor(dev); 1841e66f787SSean Bruno sub_devid = pci_get_subdevice(dev); 1851e66f787SSean Bruno 1861e66f787SSean Bruno for (m = pqi_identifiers; m->vendor != 0; m++) { 1871e66f787SSean Bruno if ((m->vendor == vendid) && (m->device == devid) && 1881e66f787SSean Bruno (m->subvendor == sub_vendid) && 1891e66f787SSean Bruno (m->subdevice == sub_devid)) { 1901e66f787SSean Bruno return (m); 1911e66f787SSean Bruno } 1921e66f787SSean Bruno } 1931e66f787SSean Bruno 1941e66f787SSean Bruno for (m = pqi_family_identifiers; m->vendor != 0; m++) { 1951e66f787SSean Bruno if ((m->vendor == vendid) && (m->device == devid)) { 1961e66f787SSean Bruno return (m); 1971e66f787SSean Bruno } 1981e66f787SSean Bruno } 1991e66f787SSean Bruno 2001e66f787SSean Bruno return (NULL); 2011e66f787SSean Bruno } 2021e66f787SSean Bruno 2031e66f787SSean Bruno /* 2041e66f787SSean Bruno * Determine whether this is one of our supported adapters. 2051e66f787SSean Bruno */ 2061e66f787SSean Bruno static int 2071e66f787SSean Bruno smartpqi_probe(device_t dev) 2081e66f787SSean Bruno { 2091e66f787SSean Bruno struct pqi_ident *id; 2101e66f787SSean Bruno 2111e66f787SSean Bruno if ((id = pqi_find_ident(dev)) != NULL) { 2121e66f787SSean Bruno device_set_desc(dev, id->desc); 2131e66f787SSean Bruno return(BUS_PROBE_VENDOR); 2141e66f787SSean Bruno } 2151e66f787SSean Bruno 2161e66f787SSean Bruno return(ENXIO); 2171e66f787SSean Bruno } 2181e66f787SSean Bruno 2191e66f787SSean Bruno /* 2201e66f787SSean Bruno * Store Bus/Device/Function in softs 2211e66f787SSean Bruno */ 2229fac68fcSPAPANI SRIKANTH void 2239fac68fcSPAPANI SRIKANTH pqisrc_save_controller_info(struct pqisrc_softstate *softs) 2241e66f787SSean Bruno { 2251e66f787SSean Bruno device_t dev = softs->os_specific.pqi_dev; 2261e66f787SSean Bruno 2271e66f787SSean Bruno softs->bus_id = (uint32_t)pci_get_bus(dev); 2281e66f787SSean Bruno softs->device_id = (uint32_t)pci_get_device(dev); 2291e66f787SSean Bruno softs->func_id = (uint32_t)pci_get_function(dev); 2301e66f787SSean Bruno } 2311e66f787SSean Bruno 2329fac68fcSPAPANI SRIKANTH 2331e66f787SSean Bruno /* 2341e66f787SSean Bruno * Allocate resources for our device, set up the bus interface. 2351e66f787SSean Bruno * Initialize the PQI related functionality, scan devices, register sim to 2361e66f787SSean Bruno * upper layer, create management interface device node etc. 2371e66f787SSean Bruno */ 2381e66f787SSean Bruno static int 2391e66f787SSean Bruno smartpqi_attach(device_t dev) 2401e66f787SSean Bruno { 2411e66f787SSean Bruno struct pqisrc_softstate *softs = NULL; 2421e66f787SSean Bruno struct pqi_ident *id = NULL; 2439fac68fcSPAPANI SRIKANTH int error = BSD_SUCCESS; 2441e66f787SSean Bruno u_int32_t command = 0, i = 0; 2451e66f787SSean Bruno int card_index = device_get_unit(dev); 2461e66f787SSean Bruno rcb_t *rcbp = NULL; 2471e66f787SSean Bruno 2481e66f787SSean Bruno /* 2491e66f787SSean Bruno * Initialise softc. 2501e66f787SSean Bruno */ 2511e66f787SSean Bruno softs = device_get_softc(dev); 2521e66f787SSean Bruno 2531e66f787SSean Bruno if (!softs) { 2541e66f787SSean Bruno printf("Could not get softc\n"); 2551e66f787SSean Bruno error = EINVAL; 2561e66f787SSean Bruno goto out; 2571e66f787SSean Bruno } 2581e66f787SSean Bruno memset(softs, 0, sizeof(*softs)); 2591e66f787SSean Bruno softs->os_specific.pqi_dev = dev; 2601e66f787SSean Bruno 2611e66f787SSean Bruno DBG_FUNC("IN\n"); 2621e66f787SSean Bruno 2631e66f787SSean Bruno /* assume failure is 'not configured' */ 2641e66f787SSean Bruno error = ENXIO; 2651e66f787SSean Bruno 2661e66f787SSean Bruno /* 2671e66f787SSean Bruno * Verify that the adapter is correctly set up in PCI space. 2681e66f787SSean Bruno */ 2691e66f787SSean Bruno pci_enable_busmaster(softs->os_specific.pqi_dev); 2701e66f787SSean Bruno command = pci_read_config(softs->os_specific.pqi_dev, PCIR_COMMAND, 2); 2711e66f787SSean Bruno if ((command & PCIM_CMD_MEMEN) == 0) { 2721e66f787SSean Bruno DBG_ERR("memory window not available command = %d\n", command); 2731e66f787SSean Bruno error = ENXIO; 2741e66f787SSean Bruno goto out; 2751e66f787SSean Bruno } 2761e66f787SSean Bruno 2771e66f787SSean Bruno /* 2781e66f787SSean Bruno * Detect the hardware interface version, set up the bus interface 2791e66f787SSean Bruno * indirection. 2801e66f787SSean Bruno */ 2811e66f787SSean Bruno id = pqi_find_ident(dev); 2829fac68fcSPAPANI SRIKANTH if (!id) { 2839fac68fcSPAPANI SRIKANTH DBG_ERR("NULL return value from pqi_find_ident\n"); 2849fac68fcSPAPANI SRIKANTH goto out; 2859fac68fcSPAPANI SRIKANTH } 2869fac68fcSPAPANI SRIKANTH 2871e66f787SSean Bruno softs->os_specific.pqi_hwif = id->hwif; 2881e66f787SSean Bruno 2891e66f787SSean Bruno switch(softs->os_specific.pqi_hwif) { 2901e66f787SSean Bruno case PQI_HWIF_SRCV: 2919fac68fcSPAPANI SRIKANTH DBG_INFO("set hardware up for PMC SRCv for %p\n", softs); 2921e66f787SSean Bruno break; 2931e66f787SSean Bruno default: 2941e66f787SSean Bruno softs->os_specific.pqi_hwif = PQI_HWIF_UNKNOWN; 2951e66f787SSean Bruno DBG_ERR("unknown hardware type\n"); 2961e66f787SSean Bruno error = ENXIO; 2971e66f787SSean Bruno goto out; 2981e66f787SSean Bruno } 2991e66f787SSean Bruno 3001e66f787SSean Bruno pqisrc_save_controller_info(softs); 3011e66f787SSean Bruno 3021e66f787SSean Bruno /* 3031e66f787SSean Bruno * Allocate the PCI register window. 3041e66f787SSean Bruno */ 3051e66f787SSean Bruno softs->os_specific.pqi_regs_rid0 = PCIR_BAR(0); 3061e66f787SSean Bruno if ((softs->os_specific.pqi_regs_res0 = 3071e66f787SSean Bruno bus_alloc_resource_any(softs->os_specific.pqi_dev, SYS_RES_MEMORY, 3081e66f787SSean Bruno &softs->os_specific.pqi_regs_rid0, RF_ACTIVE)) == NULL) { 3091e66f787SSean Bruno DBG_ERR("couldn't allocate register window 0\n"); 3101e66f787SSean Bruno /* assume failure is 'out of memory' */ 3111e66f787SSean Bruno error = ENOMEM; 3121e66f787SSean Bruno goto out; 3131e66f787SSean Bruno } 3141e66f787SSean Bruno 3151e66f787SSean Bruno bus_get_resource_start(softs->os_specific.pqi_dev, SYS_RES_MEMORY, 3161e66f787SSean Bruno softs->os_specific.pqi_regs_rid0); 3171e66f787SSean Bruno 3181e66f787SSean Bruno softs->pci_mem_handle.pqi_btag = rman_get_bustag(softs->os_specific.pqi_regs_res0); 3191e66f787SSean Bruno softs->pci_mem_handle.pqi_bhandle = rman_get_bushandle(softs->os_specific.pqi_regs_res0); 3201e66f787SSean Bruno /* softs->pci_mem_base_vaddr = (uintptr_t)rman_get_virtual(softs->os_specific.pqi_regs_res0); */ 3211e66f787SSean Bruno softs->pci_mem_base_vaddr = (char *)rman_get_virtual(softs->os_specific.pqi_regs_res0); 3221e66f787SSean Bruno 3231e66f787SSean Bruno /* 3241e66f787SSean Bruno * Allocate the parent bus DMA tag appropriate for our PCI interface. 3251e66f787SSean Bruno * 3261e66f787SSean Bruno * Note that some of these controllers are 64-bit capable. 3271e66f787SSean Bruno */ 3281e66f787SSean Bruno if (bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */ 3291e66f787SSean Bruno PAGE_SIZE, 0, /* algnmnt, boundary */ 3301e66f787SSean Bruno BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 3311e66f787SSean Bruno BUS_SPACE_MAXADDR, /* highaddr */ 3321e66f787SSean Bruno NULL, NULL, /* filter, filterarg */ 3331e66f787SSean Bruno BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 3341e66f787SSean Bruno BUS_SPACE_UNRESTRICTED, /* nsegments */ 3351e66f787SSean Bruno BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 3361e66f787SSean Bruno 0, /* flags */ 3371e66f787SSean Bruno NULL, NULL, /* No locking needed */ 3381e66f787SSean Bruno &softs->os_specific.pqi_parent_dmat)) { 3391e66f787SSean Bruno DBG_ERR("can't allocate parent DMA tag\n"); 3401e66f787SSean Bruno /* assume failure is 'out of memory' */ 3411e66f787SSean Bruno error = ENOMEM; 3421e66f787SSean Bruno goto dma_out; 3431e66f787SSean Bruno } 3441e66f787SSean Bruno 3451e66f787SSean Bruno softs->os_specific.sim_registered = FALSE; 3461e66f787SSean Bruno softs->os_name = "FreeBSD "; 3471e66f787SSean Bruno 3481e66f787SSean Bruno /* Initialize the PQI library */ 3491e66f787SSean Bruno error = pqisrc_init(softs); 3509fac68fcSPAPANI SRIKANTH if (error != PQI_STATUS_SUCCESS) { 3511e66f787SSean Bruno DBG_ERR("Failed to initialize pqi lib error = %d\n", error); 3529fac68fcSPAPANI SRIKANTH error = ENXIO; 3531e66f787SSean Bruno goto out; 3541e66f787SSean Bruno } 3559fac68fcSPAPANI SRIKANTH else { 3569fac68fcSPAPANI SRIKANTH error = BSD_SUCCESS; 3579fac68fcSPAPANI SRIKANTH } 3581e66f787SSean Bruno 3591e66f787SSean Bruno mtx_init(&softs->os_specific.cam_lock, "cam_lock", NULL, MTX_DEF); 3601e66f787SSean Bruno softs->os_specific.mtx_init = TRUE; 3611e66f787SSean Bruno mtx_init(&softs->os_specific.map_lock, "map_lock", NULL, MTX_DEF); 3629fac68fcSPAPANI SRIKANTH 3639358ccebSJohn Baldwin callout_init(&softs->os_specific.wellness_periodic, 1); 3649358ccebSJohn Baldwin callout_init(&softs->os_specific.heartbeat_timeout_id, 1); 3651e66f787SSean Bruno 3661e66f787SSean Bruno /* 3671e66f787SSean Bruno * Create DMA tag for mapping buffers into controller-addressable space. 3681e66f787SSean Bruno */ 3691e66f787SSean Bruno if (bus_dma_tag_create(softs->os_specific.pqi_parent_dmat,/* parent */ 3709fac68fcSPAPANI SRIKANTH PAGE_SIZE, 0, /* algnmnt, boundary */ 3711e66f787SSean Bruno BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ 3721e66f787SSean Bruno BUS_SPACE_MAXADDR, /* highaddr */ 3731e66f787SSean Bruno NULL, NULL, /* filter, filterarg */ 3749fac68fcSPAPANI SRIKANTH (bus_size_t)softs->pqi_cap.max_sg_elem*PAGE_SIZE,/* maxsize */ 3751e66f787SSean Bruno softs->pqi_cap.max_sg_elem, /* nsegments */ 3761e66f787SSean Bruno BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 3771e66f787SSean Bruno BUS_DMA_ALLOCNOW, /* flags */ 3781e66f787SSean Bruno busdma_lock_mutex, /* lockfunc */ 3791e66f787SSean Bruno &softs->os_specific.map_lock, /* lockfuncarg*/ 3801e66f787SSean Bruno &softs->os_specific.pqi_buffer_dmat)) { 3811e66f787SSean Bruno DBG_ERR("can't allocate buffer DMA tag for pqi_buffer_dmat\n"); 3821e66f787SSean Bruno return (ENOMEM); 3831e66f787SSean Bruno } 3841e66f787SSean Bruno 3851e66f787SSean Bruno rcbp = &softs->rcb[1]; 3861e66f787SSean Bruno for( i = 1; i <= softs->pqi_cap.max_outstanding_io; i++, rcbp++ ) { 3871e66f787SSean Bruno if ((error = bus_dmamap_create(softs->os_specific.pqi_buffer_dmat, 0, &rcbp->cm_datamap)) != 0) { 3881e66f787SSean Bruno DBG_ERR("Cant create datamap for buf @" 3891e66f787SSean Bruno "rcbp = %p maxio = %d error = %d\n", 3901e66f787SSean Bruno rcbp, softs->pqi_cap.max_outstanding_io, error); 3911e66f787SSean Bruno goto dma_out; 3921e66f787SSean Bruno } 3931e66f787SSean Bruno } 3941e66f787SSean Bruno 3951e66f787SSean Bruno os_start_heartbeat_timer((void *)softs); /* Start the heart-beat timer */ 3969358ccebSJohn Baldwin callout_reset(&softs->os_specific.wellness_periodic, 120 * hz, 3979358ccebSJohn Baldwin os_wellness_periodic, softs); 3981e66f787SSean Bruno 3991e66f787SSean Bruno error = pqisrc_scan_devices(softs); 4009fac68fcSPAPANI SRIKANTH if (error != PQI_STATUS_SUCCESS) { 4011e66f787SSean Bruno DBG_ERR("Failed to scan lib error = %d\n", error); 4029fac68fcSPAPANI SRIKANTH error = ENXIO; 4031e66f787SSean Bruno goto out; 4041e66f787SSean Bruno } 4051e66f787SSean Bruno 4061e66f787SSean Bruno error = register_sim(softs, card_index); 4071e66f787SSean Bruno if (error) { 4081e66f787SSean Bruno DBG_ERR("Failed to register sim index = %d error = %d\n", 4091e66f787SSean Bruno card_index, error); 4101e66f787SSean Bruno goto out; 4111e66f787SSean Bruno } 4121e66f787SSean Bruno 4131e66f787SSean Bruno smartpqi_target_rescan(softs); 4141e66f787SSean Bruno 4151e66f787SSean Bruno TASK_INIT(&softs->os_specific.event_task, 0, pqisrc_event_worker,softs); 4161e66f787SSean Bruno 4171e66f787SSean Bruno error = create_char_dev(softs, card_index); 4181e66f787SSean Bruno if (error) { 4191e66f787SSean Bruno DBG_ERR("Failed to register character device index=%d r=%d\n", 4201e66f787SSean Bruno card_index, error); 4211e66f787SSean Bruno goto out; 4221e66f787SSean Bruno } 4231e66f787SSean Bruno goto out; 4241e66f787SSean Bruno 4251e66f787SSean Bruno dma_out: 4261e66f787SSean Bruno if (softs->os_specific.pqi_regs_res0 != NULL) 4271e66f787SSean Bruno bus_release_resource(softs->os_specific.pqi_dev, SYS_RES_MEMORY, 4281e66f787SSean Bruno softs->os_specific.pqi_regs_rid0, 4291e66f787SSean Bruno softs->os_specific.pqi_regs_res0); 4301e66f787SSean Bruno out: 4311e66f787SSean Bruno DBG_FUNC("OUT error = %d\n", error); 4321e66f787SSean Bruno return(error); 4331e66f787SSean Bruno } 4341e66f787SSean Bruno 4351e66f787SSean Bruno /* 4361e66f787SSean Bruno * Deallocate resources for our device. 4371e66f787SSean Bruno */ 4381e66f787SSean Bruno static int 4391e66f787SSean Bruno smartpqi_detach(device_t dev) 4401e66f787SSean Bruno { 4419fac68fcSPAPANI SRIKANTH struct pqisrc_softstate *softs = device_get_softc(dev); 4429fac68fcSPAPANI SRIKANTH int rval = BSD_SUCCESS; 4439fac68fcSPAPANI SRIKANTH 4441e66f787SSean Bruno DBG_FUNC("IN\n"); 4451e66f787SSean Bruno 4469fac68fcSPAPANI SRIKANTH if (softs == NULL) 4479fac68fcSPAPANI SRIKANTH return ENXIO; 4481e66f787SSean Bruno 4491e66f787SSean Bruno /* kill the periodic event */ 4509358ccebSJohn Baldwin callout_drain(&softs->os_specific.wellness_periodic); 4511e66f787SSean Bruno /* Kill the heart beat event */ 4529358ccebSJohn Baldwin callout_drain(&softs->os_specific.heartbeat_timeout_id); 4531e66f787SSean Bruno 4549fac68fcSPAPANI SRIKANTH if (!pqisrc_ctrl_offline(softs)) { 4559fac68fcSPAPANI SRIKANTH rval = pqisrc_flush_cache(softs, PQISRC_NONE_CACHE_FLUSH_ONLY); 4569fac68fcSPAPANI SRIKANTH if (rval != PQI_STATUS_SUCCESS) { 4579fac68fcSPAPANI SRIKANTH DBG_ERR("Unable to flush adapter cache! rval = %d\n", rval); 4589fac68fcSPAPANI SRIKANTH rval = EIO; 4599fac68fcSPAPANI SRIKANTH } 4609fac68fcSPAPANI SRIKANTH } 4619fac68fcSPAPANI SRIKANTH 4621e66f787SSean Bruno destroy_char_dev(softs); 4631e66f787SSean Bruno pqisrc_uninit(softs); 4641e66f787SSean Bruno deregister_sim(softs); 4651e66f787SSean Bruno pci_release_msi(dev); 4661e66f787SSean Bruno 4671e66f787SSean Bruno DBG_FUNC("OUT\n"); 4689fac68fcSPAPANI SRIKANTH 4699fac68fcSPAPANI SRIKANTH return rval; 4701e66f787SSean Bruno } 4711e66f787SSean Bruno 4721e66f787SSean Bruno /* 4731e66f787SSean Bruno * Bring the controller to a quiescent state, ready for system suspend. 4741e66f787SSean Bruno */ 4751e66f787SSean Bruno static int 4761e66f787SSean Bruno smartpqi_suspend(device_t dev) 4771e66f787SSean Bruno { 4789fac68fcSPAPANI SRIKANTH struct pqisrc_softstate *softs = device_get_softc(dev); 4799fac68fcSPAPANI SRIKANTH 4801e66f787SSean Bruno DBG_FUNC("IN\n"); 4811e66f787SSean Bruno 4829fac68fcSPAPANI SRIKANTH if (softs == NULL) 4839fac68fcSPAPANI SRIKANTH return ENXIO; 4849fac68fcSPAPANI SRIKANTH 4851e66f787SSean Bruno DBG_INFO("Suspending the device %p\n", softs); 4861e66f787SSean Bruno softs->os_specific.pqi_state |= SMART_STATE_SUSPEND; 4871e66f787SSean Bruno 4881e66f787SSean Bruno DBG_FUNC("OUT\n"); 4899fac68fcSPAPANI SRIKANTH 4909fac68fcSPAPANI SRIKANTH return BSD_SUCCESS; 4911e66f787SSean Bruno } 4921e66f787SSean Bruno 4931e66f787SSean Bruno /* 4941e66f787SSean Bruno * Bring the controller back to a state ready for operation. 4951e66f787SSean Bruno */ 4961e66f787SSean Bruno static int 4971e66f787SSean Bruno smartpqi_resume(device_t dev) 4981e66f787SSean Bruno { 4999fac68fcSPAPANI SRIKANTH struct pqisrc_softstate *softs = device_get_softc(dev); 5009fac68fcSPAPANI SRIKANTH 5011e66f787SSean Bruno DBG_FUNC("IN\n"); 5021e66f787SSean Bruno 5039fac68fcSPAPANI SRIKANTH if (softs == NULL) 5049fac68fcSPAPANI SRIKANTH return ENXIO; 5059fac68fcSPAPANI SRIKANTH 5061e66f787SSean Bruno softs->os_specific.pqi_state &= ~SMART_STATE_SUSPEND; 5071e66f787SSean Bruno 5081e66f787SSean Bruno DBG_FUNC("OUT\n"); 5099fac68fcSPAPANI SRIKANTH 5109fac68fcSPAPANI SRIKANTH return BSD_SUCCESS; 5111e66f787SSean Bruno } 5121e66f787SSean Bruno 5131e66f787SSean Bruno /* 5141e66f787SSean Bruno * Do whatever is needed during a system shutdown. 5151e66f787SSean Bruno */ 5169fac68fcSPAPANI SRIKANTH static int 5179fac68fcSPAPANI SRIKANTH smartpqi_shutdown(device_t dev) 5181e66f787SSean Bruno { 5199fac68fcSPAPANI SRIKANTH struct pqisrc_softstate *softs = device_get_softc(dev); 5209fac68fcSPAPANI SRIKANTH int bsd_status = BSD_SUCCESS; 5219fac68fcSPAPANI SRIKANTH int pqi_status; 5221e66f787SSean Bruno 5231e66f787SSean Bruno DBG_FUNC("IN\n"); 5241e66f787SSean Bruno 5259fac68fcSPAPANI SRIKANTH if (softs == NULL) 5269fac68fcSPAPANI SRIKANTH return ENXIO; 5271e66f787SSean Bruno 5289fac68fcSPAPANI SRIKANTH if (pqisrc_ctrl_offline(softs)) 5299fac68fcSPAPANI SRIKANTH return BSD_SUCCESS; 5309fac68fcSPAPANI SRIKANTH 5319fac68fcSPAPANI SRIKANTH pqi_status = pqisrc_flush_cache(softs, PQISRC_SHUTDOWN); 5329fac68fcSPAPANI SRIKANTH if (pqi_status != PQI_STATUS_SUCCESS) { 5339fac68fcSPAPANI SRIKANTH DBG_ERR("Unable to flush adapter cache! rval = %d\n", pqi_status); 5349fac68fcSPAPANI SRIKANTH bsd_status = EIO; 5351e66f787SSean Bruno } 5361e66f787SSean Bruno 5371e66f787SSean Bruno DBG_FUNC("OUT\n"); 5381e66f787SSean Bruno 5399fac68fcSPAPANI SRIKANTH return bsd_status; 5401e66f787SSean Bruno } 5411e66f787SSean Bruno 5421e66f787SSean Bruno /* 5431e66f787SSean Bruno * PCI bus interface. 5441e66f787SSean Bruno */ 5451e66f787SSean Bruno static device_method_t pqi_methods[] = { 5461e66f787SSean Bruno /* Device interface */ 5471e66f787SSean Bruno DEVMETHOD(device_probe, smartpqi_probe), 5481e66f787SSean Bruno DEVMETHOD(device_attach, smartpqi_attach), 5491e66f787SSean Bruno DEVMETHOD(device_detach, smartpqi_detach), 5501e66f787SSean Bruno DEVMETHOD(device_suspend, smartpqi_suspend), 5511e66f787SSean Bruno DEVMETHOD(device_resume, smartpqi_resume), 5529fac68fcSPAPANI SRIKANTH DEVMETHOD(device_shutdown, smartpqi_shutdown), 5531e66f787SSean Bruno { 0, 0 } 5541e66f787SSean Bruno }; 5551e66f787SSean Bruno 5561e66f787SSean Bruno static devclass_t pqi_devclass; 5579fac68fcSPAPANI SRIKANTH 5581e66f787SSean Bruno static driver_t smartpqi_pci_driver = { 5591e66f787SSean Bruno "smartpqi", 5601e66f787SSean Bruno pqi_methods, 5611e66f787SSean Bruno sizeof(struct pqisrc_softstate) 5621e66f787SSean Bruno }; 5631e66f787SSean Bruno 5641e66f787SSean Bruno DRIVER_MODULE(smartpqi, pci, smartpqi_pci_driver, pqi_devclass, 0, 0); 5651e66f787SSean Bruno MODULE_DEPEND(smartpqi, pci, 1, 1, 1); 566