180c94ecdSKeith M Wesolowski /* 280c94ecdSKeith M Wesolowski * This file and its contents are supplied under the terms of the 380c94ecdSKeith M Wesolowski * Common Development and Distribution License ("CDDL"), version 1.0. 480c94ecdSKeith M Wesolowski * You may only use this file in accordance with the terms of version 580c94ecdSKeith M Wesolowski * 1.0 of the CDDL. 680c94ecdSKeith M Wesolowski * 780c94ecdSKeith M Wesolowski * A full copy of the text of the CDDL should have accompanied this 880c94ecdSKeith M Wesolowski * source. A copy of the CDDL is also available via the Internet at 980c94ecdSKeith M Wesolowski * http://www.illumos.org/license/CDDL. 1080c94ecdSKeith M Wesolowski */ 1180c94ecdSKeith M Wesolowski 1280c94ecdSKeith M Wesolowski /* 1380c94ecdSKeith M Wesolowski * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 1480c94ecdSKeith M Wesolowski */ 1580c94ecdSKeith M Wesolowski 1680c94ecdSKeith M Wesolowski #include "cpqary3.h" 1780c94ecdSKeith M Wesolowski 1880c94ecdSKeith M Wesolowski /* 1980c94ecdSKeith M Wesolowski * Local Autoconfiguration Function Prototype Declations 2080c94ecdSKeith M Wesolowski */ 2180c94ecdSKeith M Wesolowski 2280c94ecdSKeith M Wesolowski int cpqary3_attach(dev_info_t *, ddi_attach_cmd_t); 2380c94ecdSKeith M Wesolowski int cpqary3_detach(dev_info_t *, ddi_detach_cmd_t); 2480c94ecdSKeith M Wesolowski int cpqary3_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 2580c94ecdSKeith M Wesolowski 2680c94ecdSKeith M Wesolowski /* 2780c94ecdSKeith M Wesolowski * Local Functions Definitions 2880c94ecdSKeith M Wesolowski */ 2980c94ecdSKeith M Wesolowski 3080c94ecdSKeith M Wesolowski static void cpqary3_cleanup(cpqary3_t *, uint32_t); 3180c94ecdSKeith M Wesolowski static uint8_t cpqary3_update_ctlrdetails(cpqary3_t *, uint32_t *); 3280c94ecdSKeith M Wesolowski int8_t cpqary3_detect_target_geometry(cpqary3_t *); 3380c94ecdSKeith M Wesolowski 3480c94ecdSKeith M Wesolowski /* 3580c94ecdSKeith M Wesolowski * External Variable Definitions 3680c94ecdSKeith M Wesolowski */ 3780c94ecdSKeith M Wesolowski 3880c94ecdSKeith M Wesolowski extern cpqary3_driver_info_t gdriver_info; 3980c94ecdSKeith M Wesolowski 4080c94ecdSKeith M Wesolowski /* 4180c94ecdSKeith M Wesolowski * Global Variables Definitions 4280c94ecdSKeith M Wesolowski */ 4380c94ecdSKeith M Wesolowski 44*37245bc5SJoshua M. Clulow static char cpqary3_brief[] = "HP Smart Array (Legacy)"; 4580c94ecdSKeith M Wesolowski void *cpqary3_state; 4680c94ecdSKeith M Wesolowski 4780c94ecdSKeith M Wesolowski /* HPQaculi Changes */ 4880c94ecdSKeith M Wesolowski 4980c94ecdSKeith M Wesolowski /* 5080c94ecdSKeith M Wesolowski * HBA minor number schema 5180c94ecdSKeith M Wesolowski * 5280c94ecdSKeith M Wesolowski * The minor numbers for any minor device nodes that we create are 5380c94ecdSKeith M Wesolowski * governed by the SCSA framework. We use the macros below to 5480c94ecdSKeith M Wesolowski * fabricate minor numbers for nodes that we own. 5580c94ecdSKeith M Wesolowski * 5680c94ecdSKeith M Wesolowski * See sys/impl/transport.h for more info. 5780c94ecdSKeith M Wesolowski */ 5880c94ecdSKeith M Wesolowski 5980c94ecdSKeith M Wesolowski /* Macro to extract interface from minor number */ 6080c94ecdSKeith M Wesolowski #define CPQARY3_MINOR2INTERFACE(_x) ((_x) & (TRAN_MINOR_MASK)) 6180c94ecdSKeith M Wesolowski 6280c94ecdSKeith M Wesolowski /* Base of range assigned to HBAs: */ 6380c94ecdSKeith M Wesolowski #define SCSA_MINOR_HBABASE (32) 6480c94ecdSKeith M Wesolowski 6580c94ecdSKeith M Wesolowski /* Our minor nodes: */ 6680c94ecdSKeith M Wesolowski #define CPQARY3_MINOR (0 + SCSA_MINOR_HBABASE) 6780c94ecdSKeith M Wesolowski 6880c94ecdSKeith M Wesolowski /* Convenience macros to convert device instances to minor numbers */ 6980c94ecdSKeith M Wesolowski #define CPQARY3_INST2x(_i, _x) (((_i) << INST_MINOR_SHIFT) | (_x)) 7080c94ecdSKeith M Wesolowski #define CPQARY3_INST2CPQARY3(_i) CPQARY3_INST2x(_i, CPQARY3_MINOR) 7180c94ecdSKeith M Wesolowski 7280c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 7380c94ecdSKeith M Wesolowski 7480c94ecdSKeith M Wesolowski /* 7580c94ecdSKeith M Wesolowski * The Driver DMA Limit structure. 7680c94ecdSKeith M Wesolowski * Data used for SMART Integrated Array Controller shall be used. 7780c94ecdSKeith M Wesolowski */ 7880c94ecdSKeith M Wesolowski 7980c94ecdSKeith M Wesolowski ddi_dma_attr_t cpqary3_dma_attr = { 8080c94ecdSKeith M Wesolowski DMA_ATTR_V0, /* ddi_dma_attr version */ 8180c94ecdSKeith M Wesolowski 0, /* Low Address */ 8280c94ecdSKeith M Wesolowski 0xFFFFFFFFFFFFFFFF, /* High Address */ 8380c94ecdSKeith M Wesolowski 0x00FFFFFF, /* Max DMA Counter register */ 8480c94ecdSKeith M Wesolowski 0x20, /* Byte Alignment */ 8580c94ecdSKeith M Wesolowski 0x20, /* Burst Sizes : 32 Byte */ 8680c94ecdSKeith M Wesolowski DMA_UNIT_8, /* Minimum DMA xfer Size */ 8780c94ecdSKeith M Wesolowski 0xFFFFFFFF, /* Maximum DMA xfer Size */ 8880c94ecdSKeith M Wesolowski /* 8980c94ecdSKeith M Wesolowski * Segment boundary restrictions 9080c94ecdSKeith M Wesolowski * The addr should not cross 4GB boundry. 9180c94ecdSKeith M Wesolowski * This is required to address an issue 9280c94ecdSKeith M Wesolowski * in the Surge ASIC, with earlier FW versions. 9380c94ecdSKeith M Wesolowski */ 9480c94ecdSKeith M Wesolowski 0xFFFFFFFF, 9580c94ecdSKeith M Wesolowski CPQARY3_SG_CNT, /* Scatter/Gather List Length */ 9680c94ecdSKeith M Wesolowski 512, /* Device Granularity */ 9780c94ecdSKeith M Wesolowski 0 /* DMA flags */ 9880c94ecdSKeith M Wesolowski }; 9980c94ecdSKeith M Wesolowski 10080c94ecdSKeith M Wesolowski /* 10180c94ecdSKeith M Wesolowski * The Device Access Attribute Structure. 10280c94ecdSKeith M Wesolowski */ 10380c94ecdSKeith M Wesolowski 10480c94ecdSKeith M Wesolowski ddi_device_acc_attr_t cpqary3_dev_attributes = { 10580c94ecdSKeith M Wesolowski DDI_DEVICE_ATTR_V0, 10680c94ecdSKeith M Wesolowski DDI_STRUCTURE_LE_ACC, 10780c94ecdSKeith M Wesolowski DDI_STRICTORDER_ACC 10880c94ecdSKeith M Wesolowski }; 10980c94ecdSKeith M Wesolowski 11080c94ecdSKeith M Wesolowski /* 11180c94ecdSKeith M Wesolowski * Character-Block Operations Structure 11280c94ecdSKeith M Wesolowski */ 11380c94ecdSKeith M Wesolowski 11480c94ecdSKeith M Wesolowski static struct cb_ops cpqary3_cb_ops = { 11580c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 11680c94ecdSKeith M Wesolowski scsi_hba_open, 11780c94ecdSKeith M Wesolowski scsi_hba_close, 11880c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 11980c94ecdSKeith M Wesolowski nodev, /* cb_strategy */ 12080c94ecdSKeith M Wesolowski nodev, /* cb_print */ 12180c94ecdSKeith M Wesolowski nodev, /* cb_dump */ 12280c94ecdSKeith M Wesolowski nodev, /* cb_read */ 12380c94ecdSKeith M Wesolowski nodev, /* cb_write */ 12480c94ecdSKeith M Wesolowski cpqary3_ioctl, /* cb_ioctl */ 12580c94ecdSKeith M Wesolowski nodev, /* cb_devmap */ 12680c94ecdSKeith M Wesolowski nodev, /* cb_mmap */ 12780c94ecdSKeith M Wesolowski nodev, /* cb_segmap */ 12880c94ecdSKeith M Wesolowski nochpoll, /* cb_chpoll */ 12980c94ecdSKeith M Wesolowski ddi_prop_op, /* cb_prop_op */ 13080c94ecdSKeith M Wesolowski NULL, /* cb_stream */ 13180c94ecdSKeith M Wesolowski (int)(D_NEW|D_MP), /* cb_flag */ 13280c94ecdSKeith M Wesolowski CB_REV, 13380c94ecdSKeith M Wesolowski nodev, 13480c94ecdSKeith M Wesolowski nodev 13580c94ecdSKeith M Wesolowski }; 13680c94ecdSKeith M Wesolowski 13780c94ecdSKeith M Wesolowski /* 13880c94ecdSKeith M Wesolowski * Device Operations Structure 13980c94ecdSKeith M Wesolowski */ 14080c94ecdSKeith M Wesolowski 14180c94ecdSKeith M Wesolowski static struct dev_ops cpqary3_dev_ops = { 14280c94ecdSKeith M Wesolowski DEVO_REV, /* Driver Build Version */ 14380c94ecdSKeith M Wesolowski 0, /* Driver reference count */ 14480c94ecdSKeith M Wesolowski nodev, /* Get Info */ 14580c94ecdSKeith M Wesolowski nulldev, /* Identify not required */ 14680c94ecdSKeith M Wesolowski nulldev, /* Probe, obselete for s2.6 and up */ 14780c94ecdSKeith M Wesolowski cpqary3_attach, /* Attach routine */ 14880c94ecdSKeith M Wesolowski cpqary3_detach, /* Detach routine */ 14980c94ecdSKeith M Wesolowski nodev, /* Reset */ 15080c94ecdSKeith M Wesolowski &cpqary3_cb_ops, /* Entry Points for C&B drivers */ 15180c94ecdSKeith M Wesolowski NULL, /* Bus ops */ 15280c94ecdSKeith M Wesolowski nodev /* cpqary3_power */ 15380c94ecdSKeith M Wesolowski }; 15480c94ecdSKeith M Wesolowski 15580c94ecdSKeith M Wesolowski /* 15680c94ecdSKeith M Wesolowski * Linkage structures 15780c94ecdSKeith M Wesolowski */ 15880c94ecdSKeith M Wesolowski 15980c94ecdSKeith M Wesolowski static struct modldrv cpqary3_modldrv = { 16080c94ecdSKeith M Wesolowski &mod_driverops, /* Module Type - driver */ 16180c94ecdSKeith M Wesolowski cpqary3_brief, /* Driver Desc */ 16280c94ecdSKeith M Wesolowski &cpqary3_dev_ops /* Driver Ops */ 16380c94ecdSKeith M Wesolowski }; 16480c94ecdSKeith M Wesolowski 16580c94ecdSKeith M Wesolowski static struct modlinkage cpqary3_modlinkage = { 16680c94ecdSKeith M Wesolowski MODREV_1, /* Loadable module rev. no. */ 16780c94ecdSKeith M Wesolowski &cpqary3_modldrv, /* Loadable module */ 16880c94ecdSKeith M Wesolowski NULL /* end */ 16980c94ecdSKeith M Wesolowski }; 17080c94ecdSKeith M Wesolowski 17180c94ecdSKeith M Wesolowski 17280c94ecdSKeith M Wesolowski /* 17380c94ecdSKeith M Wesolowski * Function : _init 17480c94ecdSKeith M Wesolowski * Description : This routine allocates soft state resources for the 17580c94ecdSKeith M Wesolowski * driver, registers the HBA with the system and 17680c94ecdSKeith M Wesolowski * adds the driver(loadable module). 17780c94ecdSKeith M Wesolowski * Called By : Kernel 17880c94ecdSKeith M Wesolowski * Parameters : None 17980c94ecdSKeith M Wesolowski * Return Values: 0 / Non-Zero 18080c94ecdSKeith M Wesolowski * [as returned by the mod_install OS function] 18180c94ecdSKeith M Wesolowski */ 18280c94ecdSKeith M Wesolowski int 18380c94ecdSKeith M Wesolowski _init() 18480c94ecdSKeith M Wesolowski { 18580c94ecdSKeith M Wesolowski int retvalue; 18680c94ecdSKeith M Wesolowski 18780c94ecdSKeith M Wesolowski /* 18880c94ecdSKeith M Wesolowski * Allocate Soft State Resources; if failure, return. 18980c94ecdSKeith M Wesolowski */ 19080c94ecdSKeith M Wesolowski retvalue = ddi_soft_state_init(&cpqary3_state, 19180c94ecdSKeith M Wesolowski sizeof (cpqary3_t), MAX_CTLRS); 19280c94ecdSKeith M Wesolowski VERIFY(retvalue == 0); 19380c94ecdSKeith M Wesolowski 19480c94ecdSKeith M Wesolowski /* 19580c94ecdSKeith M Wesolowski * Initialise the HBA Interface. 19680c94ecdSKeith M Wesolowski */ 19780c94ecdSKeith M Wesolowski if (!(retvalue = scsi_hba_init(&cpqary3_modlinkage))) { 19880c94ecdSKeith M Wesolowski /* Load the driver */ 19980c94ecdSKeith M Wesolowski if ((retvalue = mod_install(&cpqary3_modlinkage))) { 20080c94ecdSKeith M Wesolowski /* 20180c94ecdSKeith M Wesolowski * Failed to load the driver, undo HBA interface 20280c94ecdSKeith M Wesolowski * and soft state allocation. 20380c94ecdSKeith M Wesolowski */ 20480c94ecdSKeith M Wesolowski scsi_hba_fini(&cpqary3_modlinkage); 20580c94ecdSKeith M Wesolowski ddi_soft_state_fini(&cpqary3_state); 20680c94ecdSKeith M Wesolowski } 20780c94ecdSKeith M Wesolowski } else { 20880c94ecdSKeith M Wesolowski /* 20980c94ecdSKeith M Wesolowski * Failed to register HBA interface, undo all soft state 21080c94ecdSKeith M Wesolowski * allocation 21180c94ecdSKeith M Wesolowski */ 21280c94ecdSKeith M Wesolowski ddi_soft_state_fini(&cpqary3_state); 21380c94ecdSKeith M Wesolowski } 21480c94ecdSKeith M Wesolowski 21580c94ecdSKeith M Wesolowski return (retvalue); 21680c94ecdSKeith M Wesolowski } 21780c94ecdSKeith M Wesolowski 21880c94ecdSKeith M Wesolowski /* 21980c94ecdSKeith M Wesolowski * Function : _fini 22080c94ecdSKeith M Wesolowski * Description : This routine removes the loadable module, cancels the 22180c94ecdSKeith M Wesolowski * HBA registration and deallocates soft state resources. 22280c94ecdSKeith M Wesolowski * Called By : Kernel 22380c94ecdSKeith M Wesolowski * Parameters : None 22480c94ecdSKeith M Wesolowski * Return Values: 0 - Success / Non-Zero - Failure 22580c94ecdSKeith M Wesolowski * [as returned by the mod_remove(OS provided) function] 22680c94ecdSKeith M Wesolowski */ 22780c94ecdSKeith M Wesolowski int 22880c94ecdSKeith M Wesolowski _fini() 22980c94ecdSKeith M Wesolowski { 23080c94ecdSKeith M Wesolowski int retvalue; 23180c94ecdSKeith M Wesolowski 23280c94ecdSKeith M Wesolowski /* Unload the Driver(loadable module) */ 23380c94ecdSKeith M Wesolowski 23480c94ecdSKeith M Wesolowski if ((retvalue = mod_remove(&cpqary3_modlinkage)) == 0) { 23580c94ecdSKeith M Wesolowski 23680c94ecdSKeith M Wesolowski /* Cancel the registeration for the HBA Interface */ 23780c94ecdSKeith M Wesolowski scsi_hba_fini(&cpqary3_modlinkage); 23880c94ecdSKeith M Wesolowski 23980c94ecdSKeith M Wesolowski /* dealloacte soft state resources of the driver */ 24080c94ecdSKeith M Wesolowski ddi_soft_state_fini(&cpqary3_state); 24180c94ecdSKeith M Wesolowski } 24280c94ecdSKeith M Wesolowski 24380c94ecdSKeith M Wesolowski return (retvalue); 24480c94ecdSKeith M Wesolowski } 24580c94ecdSKeith M Wesolowski 24680c94ecdSKeith M Wesolowski /* 24780c94ecdSKeith M Wesolowski * Function : _info 24880c94ecdSKeith M Wesolowski * Description : This routine returns information about the driver. 24980c94ecdSKeith M Wesolowski * Called By : Kernel 25080c94ecdSKeith M Wesolowski * Parameters : None 25180c94ecdSKeith M Wesolowski * Return Values: 0 / Non-Zero 25280c94ecdSKeith M Wesolowski * [as returned by mod_info(OS provided) function] 25380c94ecdSKeith M Wesolowski */ 25480c94ecdSKeith M Wesolowski int 25580c94ecdSKeith M Wesolowski _info(struct modinfo *modinfop) 25680c94ecdSKeith M Wesolowski { 25780c94ecdSKeith M Wesolowski /* 25880c94ecdSKeith M Wesolowski * Get the module information. 25980c94ecdSKeith M Wesolowski */ 26080c94ecdSKeith M Wesolowski return (mod_info(&cpqary3_modlinkage, modinfop)); 26180c94ecdSKeith M Wesolowski } 26280c94ecdSKeith M Wesolowski 26380c94ecdSKeith M Wesolowski 26480c94ecdSKeith M Wesolowski /* 26580c94ecdSKeith M Wesolowski * Function : cpqary3_attach 26680c94ecdSKeith M Wesolowski * Description : This routine initializes the driver specific soft state 26780c94ecdSKeith M Wesolowski * structure, initializes the HBA, interrupt handlers, 26880c94ecdSKeith M Wesolowski * memory pool, timeout handler, various mutex, creates the 26980c94ecdSKeith M Wesolowski * minor node. 27080c94ecdSKeith M Wesolowski * Called By : kernel 27180c94ecdSKeith M Wesolowski * Parameters : dip, command for attach 27280c94ecdSKeith M Wesolowski * Return Values: DDI_SUCCESS / DDI_FAILURE 27380c94ecdSKeith M Wesolowski * [Success on overall initialization & configuration 27480c94ecdSKeith M Wesolowski * being successful. Failure if any of the initialization 27580c94ecdSKeith M Wesolowski * or any driver-specific mandatory configuration fails] 27680c94ecdSKeith M Wesolowski */ 27780c94ecdSKeith M Wesolowski int 27880c94ecdSKeith M Wesolowski cpqary3_attach(dev_info_t *dip, ddi_attach_cmd_t attach_cmd) 27980c94ecdSKeith M Wesolowski { 28080c94ecdSKeith M Wesolowski int8_t minor_node_name[14]; 28180c94ecdSKeith M Wesolowski uint32_t instance; 28280c94ecdSKeith M Wesolowski uint32_t retvalue; 28380c94ecdSKeith M Wesolowski uint32_t cleanstatus = 0; 28480c94ecdSKeith M Wesolowski cpqary3_t *cpqary3p; /* per-controller */ 28580c94ecdSKeith M Wesolowski ddi_dma_attr_t tmp_dma_attr; 28680c94ecdSKeith M Wesolowski 28780c94ecdSKeith M Wesolowski /* Return Failure, If the Command is other than - DDI_ATTACH. */ 28880c94ecdSKeith M Wesolowski 28980c94ecdSKeith M Wesolowski if (attach_cmd != DDI_ATTACH) 29080c94ecdSKeith M Wesolowski return (DDI_FAILURE); 29180c94ecdSKeith M Wesolowski 29280c94ecdSKeith M Wesolowski /* Get the Instance of the Device */ 29380c94ecdSKeith M Wesolowski 29480c94ecdSKeith M Wesolowski instance = ddi_get_instance(dip); 29580c94ecdSKeith M Wesolowski 29680c94ecdSKeith M Wesolowski /* Allocate the per-device-instance soft state structure */ 29780c94ecdSKeith M Wesolowski 29880c94ecdSKeith M Wesolowski retvalue = ddi_soft_state_zalloc(cpqary3_state, instance); 29980c94ecdSKeith M Wesolowski VERIFY(retvalue == 0); 30080c94ecdSKeith M Wesolowski 30180c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_SOFTSTATE_ALLOC_DONE; 30280c94ecdSKeith M Wesolowski 30380c94ecdSKeith M Wesolowski /* Per Controller Pointer */ 30480c94ecdSKeith M Wesolowski cpqary3p = ddi_get_soft_state(cpqary3_state, instance); 30580c94ecdSKeith M Wesolowski if (!cpqary3p) { 30680c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3: Soft State Retrieval Failed"); 30780c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 30880c94ecdSKeith M Wesolowski return (DDI_FAILURE); 30980c94ecdSKeith M Wesolowski } 31080c94ecdSKeith M Wesolowski 31180c94ecdSKeith M Wesolowski /* Maintain a record in per-ctlr structure */ 31280c94ecdSKeith M Wesolowski cpqary3p->dip = dip; 31380c94ecdSKeith M Wesolowski cpqary3p->instance = instance; 31480c94ecdSKeith M Wesolowski 31580c94ecdSKeith M Wesolowski /* Get the User Configuration information from Driver's conf File */ 31680c94ecdSKeith M Wesolowski cpqary3_read_conf_file(dip, cpqary3p); 31780c94ecdSKeith M Wesolowski 31880c94ecdSKeith M Wesolowski /* Get and Map the HW Configuration */ 31980c94ecdSKeith M Wesolowski retvalue = cpqary3_update_ctlrdetails(cpqary3p, &cleanstatus); 32080c94ecdSKeith M Wesolowski if (retvalue == CPQARY3_FAILURE) { 32180c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 32280c94ecdSKeith M Wesolowski return (DDI_FAILURE); 32380c94ecdSKeith M Wesolowski } 32480c94ecdSKeith M Wesolowski 32580c94ecdSKeith M Wesolowski /* Get the Cookie for hardware Interrupt Handler */ 32680c94ecdSKeith M Wesolowski if (ddi_get_iblock_cookie(dip, 0, &cpqary3p->hw_iblock_cookie) != 32780c94ecdSKeith M Wesolowski DDI_SUCCESS) { 32880c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 32980c94ecdSKeith M Wesolowski return (DDI_FAILURE); 33080c94ecdSKeith M Wesolowski } 33180c94ecdSKeith M Wesolowski 33280c94ecdSKeith M Wesolowski /* Initialize Per Controller Mutex */ 33380c94ecdSKeith M Wesolowski mutex_init(&cpqary3p->hw_mutex, NULL, MUTEX_DRIVER, 33480c94ecdSKeith M Wesolowski (void *)cpqary3p->hw_iblock_cookie); 33580c94ecdSKeith M Wesolowski 33680c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_MUTEX_INIT_DONE; 33780c94ecdSKeith M Wesolowski 33880c94ecdSKeith M Wesolowski /* Get the Cookie for Soft(low level) Interrupt Handler */ 33980c94ecdSKeith M Wesolowski if (ddi_get_soft_iblock_cookie(dip, DDI_SOFTINT_HIGH, 34080c94ecdSKeith M Wesolowski &cpqary3p->sw_iblock_cookie) != DDI_SUCCESS) { 34180c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 34280c94ecdSKeith M Wesolowski return (DDI_FAILURE); 34380c94ecdSKeith M Wesolowski } 34480c94ecdSKeith M Wesolowski 34580c94ecdSKeith M Wesolowski /* Initialize the s/w Mutex */ 34680c94ecdSKeith M Wesolowski mutex_init(&cpqary3p->sw_mutex, NULL, MUTEX_DRIVER, 34780c94ecdSKeith M Wesolowski (void *)cpqary3p->sw_iblock_cookie); 34880c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_SW_MUTEX_INIT_DONE; 34980c94ecdSKeith M Wesolowski 35080c94ecdSKeith M Wesolowski /* Initialize per Controller private details */ 35180c94ecdSKeith M Wesolowski retvalue = cpqary3_init_ctlr_resource(cpqary3p); 35280c94ecdSKeith M Wesolowski if (retvalue != CPQARY3_SUCCESS) { 35380c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 35480c94ecdSKeith M Wesolowski return (DDI_FAILURE); 35580c94ecdSKeith M Wesolowski } 35680c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_CTLR_CONFIG_DONE; 35780c94ecdSKeith M Wesolowski 35880c94ecdSKeith M Wesolowski /* 35980c94ecdSKeith M Wesolowski * Allocate HBA transport structure 36080c94ecdSKeith M Wesolowski */ 36180c94ecdSKeith M Wesolowski cpqary3p->hba_tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); 36280c94ecdSKeith M Wesolowski if (!cpqary3p->hba_tran) { 36380c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 36480c94ecdSKeith M Wesolowski return (DDI_FAILURE); 36580c94ecdSKeith M Wesolowski } 36680c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_HBA_TRAN_ALLOC_DONE; 36780c94ecdSKeith M Wesolowski 36880c94ecdSKeith M Wesolowski /* 36980c94ecdSKeith M Wesolowski * Set private field for the HBA tran structure. 37080c94ecdSKeith M Wesolowski * Initialise the HBA tran entry points. 37180c94ecdSKeith M Wesolowski * Attach the controller to HBA. 37280c94ecdSKeith M Wesolowski */ 37380c94ecdSKeith M Wesolowski cpqary3_init_hbatran(cpqary3p); 37480c94ecdSKeith M Wesolowski 37580c94ecdSKeith M Wesolowski /* PERF */ 37680c94ecdSKeith M Wesolowski /* SG */ 37780c94ecdSKeith M Wesolowski tmp_dma_attr = cpqary3_dma_attr; 37880c94ecdSKeith M Wesolowski tmp_dma_attr.dma_attr_sgllen = cpqary3p->sg_cnt; 37980c94ecdSKeith M Wesolowski /* SG */ 38080c94ecdSKeith M Wesolowski /* PERF */ 38180c94ecdSKeith M Wesolowski /* 38280c94ecdSKeith M Wesolowski * Register the DMA attributes and the transport vectors 38380c94ecdSKeith M Wesolowski * of each instance of the HBA device. 38480c94ecdSKeith M Wesolowski */ 38580c94ecdSKeith M Wesolowski if (scsi_hba_attach_setup(dip, &tmp_dma_attr, cpqary3p->hba_tran, 38680c94ecdSKeith M Wesolowski SCSI_HBA_TRAN_CLONE) == DDI_FAILURE) { 38780c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 38880c94ecdSKeith M Wesolowski return (DDI_FAILURE); 38980c94ecdSKeith M Wesolowski } 39080c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_HBA_TRAN_ATTACH_DONE; 39180c94ecdSKeith M Wesolowski 39280c94ecdSKeith M Wesolowski /* 39380c94ecdSKeith M Wesolowski * Create a minor node for Ioctl interface. 39480c94ecdSKeith M Wesolowski * The nomenclature used will be "cpqary3" immediately followed by 39580c94ecdSKeith M Wesolowski * the current driver instance in the system. 39680c94ecdSKeith M Wesolowski * for e.g.: for 0th instance : cpqary3,0 39780c94ecdSKeith M Wesolowski * for 1st instance : cpqary3,1 39880c94ecdSKeith M Wesolowski */ 39980c94ecdSKeith M Wesolowski 40080c94ecdSKeith M Wesolowski (void) sprintf(minor_node_name, "cpqary3,%d", instance); 40180c94ecdSKeith M Wesolowski 40280c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 40380c94ecdSKeith M Wesolowski if (ddi_create_minor_node(dip, minor_node_name, S_IFCHR, 40480c94ecdSKeith M Wesolowski CPQARY3_INST2CPQARY3(instance), DDI_NT_SCSI_NEXUS, 0) == 40580c94ecdSKeith M Wesolowski DDI_SUCCESS) { 40680c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 40780c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_CREATE_MINOR_NODE; 40880c94ecdSKeith M Wesolowski } else { 40980c94ecdSKeith M Wesolowski cmn_err(CE_NOTE, "CPQary3 : Failed to create minor node"); 41080c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 41180c94ecdSKeith M Wesolowski return (DDI_FAILURE); 41280c94ecdSKeith M Wesolowski } 41380c94ecdSKeith M Wesolowski 41480c94ecdSKeith M Wesolowski 41580c94ecdSKeith M Wesolowski /* Register a timeout driver-routine to be called every 2 secs */ 41680c94ecdSKeith M Wesolowski cpqary3p->tick_tmout_id = timeout(cpqary3_tick_hdlr, 41780c94ecdSKeith M Wesolowski (caddr_t)cpqary3p, drv_usectohz(CPQARY3_TICKTMOUT_VALUE)); 41880c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_TICK_TMOUT_REGD; 41980c94ecdSKeith M Wesolowski 42080c94ecdSKeith M Wesolowski /* Register Software Interrupt Handler */ 42180c94ecdSKeith M Wesolowski if (ddi_add_softintr(dip, DDI_SOFTINT_HIGH, 42280c94ecdSKeith M Wesolowski &cpqary3p->cpqary3_softintr_id, &cpqary3p->sw_iblock_cookie, NULL, 42380c94ecdSKeith M Wesolowski cpqary3_sw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) { 42480c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 42580c94ecdSKeith M Wesolowski return (DDI_FAILURE); 42680c94ecdSKeith M Wesolowski } 42780c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_SW_INTR_HDLR_SET; 42880c94ecdSKeith M Wesolowski 42980c94ecdSKeith M Wesolowski /* Register Interrupt Handler */ 43080c94ecdSKeith M Wesolowski if (ddi_add_intr(dip, 0, &cpqary3p->hw_iblock_cookie, NULL, 43180c94ecdSKeith M Wesolowski cpqary3_hw_isr, (caddr_t)cpqary3p) != DDI_SUCCESS) { 43280c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, cleanstatus); 43380c94ecdSKeith M Wesolowski return (DDI_FAILURE); 43480c94ecdSKeith M Wesolowski } 43580c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_INTR_HDLR_SET; 43680c94ecdSKeith M Wesolowski 43780c94ecdSKeith M Wesolowski /* Enable the Controller Interrupt */ 43880c94ecdSKeith M Wesolowski cpqary3_intr_onoff(cpqary3p, CPQARY3_INTR_ENABLE); 43980c94ecdSKeith M Wesolowski if (cpqary3p->host_support & 0x4) 44080c94ecdSKeith M Wesolowski cpqary3_lockup_intr_onoff(cpqary3p, CPQARY3_LOCKUP_INTR_ENABLE); 44180c94ecdSKeith M Wesolowski 44280c94ecdSKeith M Wesolowski /* 44380c94ecdSKeith M Wesolowski * We have come with hmaeventd - which logs the storage events on 44480c94ecdSKeith M Wesolowski * console as well as in IML. So we are commenting the NOE support in 44580c94ecdSKeith M Wesolowski * the driver 44680c94ecdSKeith M Wesolowski */ 44780c94ecdSKeith M Wesolowski 44880c94ecdSKeith M Wesolowski /* NOE */ 44980c94ecdSKeith M Wesolowski if (cpqary3p->noe_support == 1) { 45080c94ecdSKeith M Wesolowski /* Enable the Notification on Event in this controller */ 45180c94ecdSKeith M Wesolowski if (CPQARY3_SUCCESS == 45280c94ecdSKeith M Wesolowski cpqary3_send_NOE_command(cpqary3p, 45380c94ecdSKeith M Wesolowski NULL, CPQARY3_NOE_INIT)) { 45480c94ecdSKeith M Wesolowski cleanstatus |= CPQARY3_NOE_INIT_DONE; 45580c94ecdSKeith M Wesolowski } else { 45680c94ecdSKeith M Wesolowski cmn_err(CE_CONT, "CPQary3 : Failed to initialize " 45780c94ecdSKeith M Wesolowski "NOTIFICATION ON EVENT \n"); 45880c94ecdSKeith M Wesolowski } 45980c94ecdSKeith M Wesolowski } 46080c94ecdSKeith M Wesolowski /* NOE */ 46180c94ecdSKeith M Wesolowski 46280c94ecdSKeith M Wesolowski /* Report that an Instance of the Driver is Attached Successfully */ 46380c94ecdSKeith M Wesolowski ddi_report_dev(dip); 46480c94ecdSKeith M Wesolowski 46580c94ecdSKeith M Wesolowski /* 46680c94ecdSKeith M Wesolowski * Now update the num_ctlr 46780c94ecdSKeith M Wesolowski * This is required for the agents 46880c94ecdSKeith M Wesolowski */ 46980c94ecdSKeith M Wesolowski 47080c94ecdSKeith M Wesolowski gdriver_info.num_ctlr++; 47180c94ecdSKeith M Wesolowski 47280c94ecdSKeith M Wesolowski return (DDI_SUCCESS); 47380c94ecdSKeith M Wesolowski 47480c94ecdSKeith M Wesolowski } 47580c94ecdSKeith M Wesolowski 47680c94ecdSKeith M Wesolowski /* 47780c94ecdSKeith M Wesolowski * Function : cpqary3_detach 47880c94ecdSKeith M Wesolowski * Description : This routine removes the state associated with a 47980c94ecdSKeith M Wesolowski * given instance of a device node prior to the 48080c94ecdSKeith M Wesolowski * removal of that instance from the system 48180c94ecdSKeith M Wesolowski * Called By : kernel 48280c94ecdSKeith M Wesolowski * Parameters : dip, command for detach 48380c94ecdSKeith M Wesolowski * Return Values: DDI_SUCCESS / DDI_FAILURE 48480c94ecdSKeith M Wesolowski * [failure ONLY if the command sent with this function 48580c94ecdSKeith M Wesolowski * as a paramter is not DETACH] 48680c94ecdSKeith M Wesolowski */ 48780c94ecdSKeith M Wesolowski int 48880c94ecdSKeith M Wesolowski cpqary3_detach(dev_info_t *dip, ddi_detach_cmd_t detach_cmd) 48980c94ecdSKeith M Wesolowski { 49080c94ecdSKeith M Wesolowski cpqary3_t *cpqary3p; 49180c94ecdSKeith M Wesolowski scsi_hba_tran_t *hba_tran; 49280c94ecdSKeith M Wesolowski 49380c94ecdSKeith M Wesolowski /* Return failure, If Command is not DDI_DETACH */ 49480c94ecdSKeith M Wesolowski 49580c94ecdSKeith M Wesolowski if (DDI_DETACH != detach_cmd) 49680c94ecdSKeith M Wesolowski return (DDI_FAILURE); 49780c94ecdSKeith M Wesolowski 49880c94ecdSKeith M Wesolowski /* 49980c94ecdSKeith M Wesolowski * Get scsi_hba_tran structure. 50080c94ecdSKeith M Wesolowski * Get per controller structure. 50180c94ecdSKeith M Wesolowski */ 50280c94ecdSKeith M Wesolowski 50380c94ecdSKeith M Wesolowski hba_tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip); 50480c94ecdSKeith M Wesolowski cpqary3p = (cpqary3_t *)hba_tran->tran_hba_private; 50580c94ecdSKeith M Wesolowski 50680c94ecdSKeith M Wesolowski /* Flush the cache */ 50780c94ecdSKeith M Wesolowski 50880c94ecdSKeith M Wesolowski cpqary3_flush_cache(cpqary3p); 50980c94ecdSKeith M Wesolowski 51080c94ecdSKeith M Wesolowski /* Undo cpqary3_attach */ 51180c94ecdSKeith M Wesolowski 51280c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3p, CPQARY3_CLEAN_ALL); 51380c94ecdSKeith M Wesolowski 51480c94ecdSKeith M Wesolowski return (DDI_SUCCESS); 51580c94ecdSKeith M Wesolowski 51680c94ecdSKeith M Wesolowski } 51780c94ecdSKeith M Wesolowski 51880c94ecdSKeith M Wesolowski /* 51980c94ecdSKeith M Wesolowski * Function : cpary3_ioctl 52080c94ecdSKeith M Wesolowski * Description : This routine services ioctl requests. 52180c94ecdSKeith M Wesolowski * Called By : kernel 52280c94ecdSKeith M Wesolowski * Parameters : Too many to list. Please look below !!! 52380c94ecdSKeith M Wesolowski * Return Values: 0 / EINVAL / EFAULT / 52480c94ecdSKeith M Wesolowski * [0 on normal successful completion of the ioctl 52580c94ecdSKeith M Wesolowski * request] 52680c94ecdSKeith M Wesolowski */ 52780c94ecdSKeith M Wesolowski int 52880c94ecdSKeith M Wesolowski cpqary3_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 52980c94ecdSKeith M Wesolowski int *retvaluep) 53080c94ecdSKeith M Wesolowski { 53180c94ecdSKeith M Wesolowski minor_t cpqary3_minor_num; 53280c94ecdSKeith M Wesolowski cpqary3_t *cpqary3p; 53380c94ecdSKeith M Wesolowski int instance; 53480c94ecdSKeith M Wesolowski 53580c94ecdSKeith M Wesolowski /* 53680c94ecdSKeith M Wesolowski * Get the soft state structure for this instance 53780c94ecdSKeith M Wesolowski * Return ENODEV if the structure does not exist. 53880c94ecdSKeith M Wesolowski */ 53980c94ecdSKeith M Wesolowski 54080c94ecdSKeith M Wesolowski /* 54180c94ecdSKeith M Wesolowski * minor() call used in cpqary3_ioctl() returns minor number of the 54280c94ecdSKeith M Wesolowski * device which are in the 54380c94ecdSKeith M Wesolowski * range 0-255. if the minor number of the device is greater than 255, 54480c94ecdSKeith M Wesolowski * data will get truncated. so we are now using getminor(), 54580c94ecdSKeith M Wesolowski * instead of minor() 54680c94ecdSKeith M Wesolowski */ 54780c94ecdSKeith M Wesolowski 54880c94ecdSKeith M Wesolowski if (EINVAL == (cpqary3_minor_num = getminor(dev))) { 54980c94ecdSKeith M Wesolowski *retvaluep = ENODEV; 55080c94ecdSKeith M Wesolowski return (*retvaluep); 55180c94ecdSKeith M Wesolowski } 55280c94ecdSKeith M Wesolowski 55380c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 55480c94ecdSKeith M Wesolowski 55580c94ecdSKeith M Wesolowski /* get instance */ 55680c94ecdSKeith M Wesolowski instance = MINOR2INST(cpqary3_minor_num); 55780c94ecdSKeith M Wesolowski 55880c94ecdSKeith M Wesolowski cpqary3p = (cpqary3_t *)ddi_get_soft_state(cpqary3_state, instance); 55980c94ecdSKeith M Wesolowski 56080c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 56180c94ecdSKeith M Wesolowski 56280c94ecdSKeith M Wesolowski if (!cpqary3p) { 56380c94ecdSKeith M Wesolowski *retvaluep = ENODEV; 56480c94ecdSKeith M Wesolowski return (*retvaluep); 56580c94ecdSKeith M Wesolowski } 56680c94ecdSKeith M Wesolowski 56780c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 56880c94ecdSKeith M Wesolowski 56980c94ecdSKeith M Wesolowski /* check which interface is being requested */ 57080c94ecdSKeith M Wesolowski if (CPQARY3_MINOR2INTERFACE(cpqary3_minor_num) != CPQARY3_MINOR) { 57180c94ecdSKeith M Wesolowski /* defer to SCSA */ 57280c94ecdSKeith M Wesolowski return (scsi_hba_ioctl(dev, cmd, arg, mode, credp, retvaluep)); 57380c94ecdSKeith M Wesolowski } 57480c94ecdSKeith M Wesolowski 57580c94ecdSKeith M Wesolowski /* HPQacucli Changes */ 57680c94ecdSKeith M Wesolowski 57780c94ecdSKeith M Wesolowski switch (cmd) { 57880c94ecdSKeith M Wesolowski case CPQARY3_IOCTL_DRIVER_INFO: 57980c94ecdSKeith M Wesolowski *retvaluep = 58080c94ecdSKeith M Wesolowski cpqary3_ioctl_driver_info(arg, mode); 58180c94ecdSKeith M Wesolowski break; 58280c94ecdSKeith M Wesolowski 58380c94ecdSKeith M Wesolowski case CPQARY3_IOCTL_CTLR_INFO: 58480c94ecdSKeith M Wesolowski *retvaluep = 58580c94ecdSKeith M Wesolowski cpqary3_ioctl_ctlr_info(arg, cpqary3p, mode); 58680c94ecdSKeith M Wesolowski break; 58780c94ecdSKeith M Wesolowski 58880c94ecdSKeith M Wesolowski case CPQARY3_IOCTL_BMIC_PASS: 58980c94ecdSKeith M Wesolowski *retvaluep = 59080c94ecdSKeith M Wesolowski cpqary3_ioctl_bmic_pass(arg, cpqary3p, mode); 59180c94ecdSKeith M Wesolowski break; 59280c94ecdSKeith M Wesolowski 59380c94ecdSKeith M Wesolowski case CPQARY3_IOCTL_SCSI_PASS: 59480c94ecdSKeith M Wesolowski *retvaluep = 59580c94ecdSKeith M Wesolowski cpqary3_ioctl_scsi_pass(arg, cpqary3p, mode); 59680c94ecdSKeith M Wesolowski break; 59780c94ecdSKeith M Wesolowski 59880c94ecdSKeith M Wesolowski default: 59980c94ecdSKeith M Wesolowski *retvaluep = EINVAL; 60080c94ecdSKeith M Wesolowski break; 60180c94ecdSKeith M Wesolowski } 60280c94ecdSKeith M Wesolowski return (*retvaluep); 60380c94ecdSKeith M Wesolowski 60480c94ecdSKeith M Wesolowski 60580c94ecdSKeith M Wesolowski } 60680c94ecdSKeith M Wesolowski 60780c94ecdSKeith M Wesolowski 60880c94ecdSKeith M Wesolowski /* 60980c94ecdSKeith M Wesolowski * Function : cqpary3_cleanup 61080c94ecdSKeith M Wesolowski * Description : This routine frees all allocated resources. 61180c94ecdSKeith M Wesolowski * Called By : kernel 61280c94ecdSKeith M Wesolowski * Parameters : per-controller, bit-map(stating what all to clean) 61380c94ecdSKeith M Wesolowski * Return Values: None 61480c94ecdSKeith M Wesolowski */ 61580c94ecdSKeith M Wesolowski static void 61680c94ecdSKeith M Wesolowski cpqary3_cleanup(cpqary3_t *cpqary3p, uint32_t status) 61780c94ecdSKeith M Wesolowski { 61880c94ecdSKeith M Wesolowski int8_t node_name[10]; 61980c94ecdSKeith M Wesolowski clock_t cpqary3_lbolt; 62080c94ecdSKeith M Wesolowski uint32_t targ; 62180c94ecdSKeith M Wesolowski 62280c94ecdSKeith M Wesolowski ASSERT(cpqary3p != NULL); 62380c94ecdSKeith M Wesolowski 62480c94ecdSKeith M Wesolowski /* 62580c94ecdSKeith M Wesolowski * Disable the NOE command 62680c94ecdSKeith M Wesolowski * Free the Command Memory Pool 62780c94ecdSKeith M Wesolowski * destroy all conditional variables 62880c94ecdSKeith M Wesolowski */ 62980c94ecdSKeith M Wesolowski 63080c94ecdSKeith M Wesolowski /* 63180c94ecdSKeith M Wesolowski * We have removed NOE functionality from the 63280c94ecdSKeith M Wesolowski * driver. So commenting the below piece of code 63380c94ecdSKeith M Wesolowski */ 63480c94ecdSKeith M Wesolowski 63580c94ecdSKeith M Wesolowski if (status & CPQARY3_NOE_INIT_DONE) { 63680c94ecdSKeith M Wesolowski if (CPQARY3_SUCCESS == cpqary3_disable_NOE_command(cpqary3p)) { 63780c94ecdSKeith M Wesolowski mutex_enter(&cpqary3p->hw_mutex); 63880c94ecdSKeith M Wesolowski cpqary3_lbolt = ddi_get_lbolt(); 63980c94ecdSKeith M Wesolowski if (DDI_FAILURE == 64080c94ecdSKeith M Wesolowski cv_timedwait_sig(&cpqary3p->cv_noe_wait, 64180c94ecdSKeith M Wesolowski &cpqary3p->hw_mutex, 64280c94ecdSKeith M Wesolowski cpqary3_lbolt + drv_usectohz(3000000))) { 64380c94ecdSKeith M Wesolowski cmn_err(CE_NOTE, 64480c94ecdSKeith M Wesolowski "CPQary3: Resume signal for disable NOE " 64580c94ecdSKeith M Wesolowski "command not received \n"); 64680c94ecdSKeith M Wesolowski } 64780c94ecdSKeith M Wesolowski mutex_exit(&cpqary3p->hw_mutex); 64880c94ecdSKeith M Wesolowski } 64980c94ecdSKeith M Wesolowski } 65080c94ecdSKeith M Wesolowski 65180c94ecdSKeith M Wesolowski /* 65280c94ecdSKeith M Wesolowski * Detach the device 65380c94ecdSKeith M Wesolowski * Free / Release / Destroy the following entities/resources: 65480c94ecdSKeith M Wesolowski * transport layer 65580c94ecdSKeith M Wesolowski * h/w & s/w interrupt handlers 65680c94ecdSKeith M Wesolowski * all mutex 65780c94ecdSKeith M Wesolowski * timeout handler 65880c94ecdSKeith M Wesolowski * target structure 65980c94ecdSKeith M Wesolowski * minor node 66080c94ecdSKeith M Wesolowski * soft state 66180c94ecdSKeith M Wesolowski * any register/memory mapping 66280c94ecdSKeith M Wesolowski */ 66380c94ecdSKeith M Wesolowski 66480c94ecdSKeith M Wesolowski if (status & CPQARY3_INTR_HDLR_SET) 66580c94ecdSKeith M Wesolowski ddi_remove_intr(cpqary3p->dip, 0, cpqary3p->hw_iblock_cookie); 66680c94ecdSKeith M Wesolowski 66780c94ecdSKeith M Wesolowski if (status & CPQARY3_SW_INTR_HDLR_SET) 66880c94ecdSKeith M Wesolowski ddi_remove_softintr(cpqary3p->cpqary3_softintr_id); 66980c94ecdSKeith M Wesolowski 67080c94ecdSKeith M Wesolowski if ((status & CPQARY3_TICK_TMOUT_REGD) && cpqary3p->tick_tmout_id) { 67180c94ecdSKeith M Wesolowski VERIFY(untimeout(cpqary3p->tick_tmout_id) >= 0); 67280c94ecdSKeith M Wesolowski cpqary3p->tick_tmout_id = NULL; 67380c94ecdSKeith M Wesolowski } 67480c94ecdSKeith M Wesolowski 67580c94ecdSKeith M Wesolowski if (status & CPQARY3_CREATE_MINOR_NODE) { 67680c94ecdSKeith M Wesolowski (void) sprintf(node_name, "cpqary3%d", cpqary3p->instance); 67780c94ecdSKeith M Wesolowski ddi_remove_minor_node(cpqary3p->dip, node_name); 67880c94ecdSKeith M Wesolowski } 67980c94ecdSKeith M Wesolowski 68080c94ecdSKeith M Wesolowski if (status & CPQARY3_HBA_TRAN_ATTACH_DONE) 68180c94ecdSKeith M Wesolowski (void) scsi_hba_detach(cpqary3p->dip); 68280c94ecdSKeith M Wesolowski 68380c94ecdSKeith M Wesolowski if (status & CPQARY3_HBA_TRAN_ALLOC_DONE) 68480c94ecdSKeith M Wesolowski scsi_hba_tran_free(cpqary3p->hba_tran); 68580c94ecdSKeith M Wesolowski 68680c94ecdSKeith M Wesolowski if (status & CPQARY3_CTLR_CONFIG_DONE) { 68780c94ecdSKeith M Wesolowski mutex_enter(&cpqary3p->hw_mutex); 68880c94ecdSKeith M Wesolowski 68980c94ecdSKeith M Wesolowski cv_destroy(&cpqary3p->cv_abort_wait); 69080c94ecdSKeith M Wesolowski cv_destroy(&cpqary3p->cv_flushcache_wait); 69180c94ecdSKeith M Wesolowski cv_destroy(&cpqary3p->cv_noe_wait); 69280c94ecdSKeith M Wesolowski cv_destroy(&cpqary3p->cv_immediate_wait); 69380c94ecdSKeith M Wesolowski cv_destroy(&cpqary3p->cv_ioctl_wait); 69480c94ecdSKeith M Wesolowski 69580c94ecdSKeith M Wesolowski for (targ = 0; targ < CPQARY3_MAX_TGT; targ++) { 69680c94ecdSKeith M Wesolowski if (cpqary3p->cpqary3_tgtp[targ] == NULL) 69780c94ecdSKeith M Wesolowski continue; 69880c94ecdSKeith M Wesolowski MEM_SFREE(cpqary3p->cpqary3_tgtp[targ], 69980c94ecdSKeith M Wesolowski sizeof (cpqary3_tgt_t)); 70080c94ecdSKeith M Wesolowski } 70180c94ecdSKeith M Wesolowski 70280c94ecdSKeith M Wesolowski mutex_exit(&cpqary3p->hw_mutex); 70380c94ecdSKeith M Wesolowski 70480c94ecdSKeith M Wesolowski cpqary3_memfini(cpqary3p, CPQARY3_MEMLIST_DONE | 70580c94ecdSKeith M Wesolowski CPQARY3_PHYCTGS_DONE | CPQARY3_CMDMEM_DONE); 70680c94ecdSKeith M Wesolowski } 70780c94ecdSKeith M Wesolowski 70880c94ecdSKeith M Wesolowski if (status & CPQARY3_SW_MUTEX_INIT_DONE) 70980c94ecdSKeith M Wesolowski mutex_destroy(&cpqary3p->sw_mutex); 71080c94ecdSKeith M Wesolowski 71180c94ecdSKeith M Wesolowski if (status & CPQARY3_MUTEX_INIT_DONE) 71280c94ecdSKeith M Wesolowski mutex_destroy(&cpqary3p->hw_mutex); 71380c94ecdSKeith M Wesolowski 71480c94ecdSKeith M Wesolowski /* 71580c94ecdSKeith M Wesolowski * If this flag is set, free all mapped registers 71680c94ecdSKeith M Wesolowski */ 71780c94ecdSKeith M Wesolowski if (status & CPQARY3_MEM_MAPPED) { 71880c94ecdSKeith M Wesolowski if (cpqary3p->idr_handle) 71980c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->idr_handle); 72080c94ecdSKeith M Wesolowski if (cpqary3p->isr_handle) 72180c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->isr_handle); 72280c94ecdSKeith M Wesolowski if (cpqary3p->imr_handle) 72380c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->imr_handle); 72480c94ecdSKeith M Wesolowski if (cpqary3p->ipq_handle) 72580c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->ipq_handle); 72680c94ecdSKeith M Wesolowski if (cpqary3p->opq_handle) 72780c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->opq_handle); 72880c94ecdSKeith M Wesolowski if (cpqary3p->ct_handle) 72980c94ecdSKeith M Wesolowski ddi_regs_map_free(&cpqary3p->ct_handle); 73080c94ecdSKeith M Wesolowski } 73180c94ecdSKeith M Wesolowski 73280c94ecdSKeith M Wesolowski if (status & CPQARY3_SOFTSTATE_ALLOC_DONE) { 73380c94ecdSKeith M Wesolowski ddi_soft_state_free(cpqary3_state, 73480c94ecdSKeith M Wesolowski ddi_get_instance(cpqary3p->dip)); 73580c94ecdSKeith M Wesolowski } 73680c94ecdSKeith M Wesolowski } 73780c94ecdSKeith M Wesolowski 73880c94ecdSKeith M Wesolowski /* 73980c94ecdSKeith M Wesolowski * Function : cpqary3_update_ctlrdetails 74080c94ecdSKeith M Wesolowski * Description : Performs Sanity check of the hw, Updates PCI Config 74180c94ecdSKeith M Wesolowski * Information, Verifies the supported board-id and 74280c94ecdSKeith M Wesolowski * Sets up a mapping for the Primary I2O Memory BAR and 74380c94ecdSKeith M Wesolowski * the Primary DRAM 1 BAR to access Host Interface 74480c94ecdSKeith M Wesolowski * registers and the Transport Configuration table. 74580c94ecdSKeith M Wesolowski * Called By : cpqary3_attach() 74680c94ecdSKeith M Wesolowski * Parameters : per-controller, bitmap (used for cleaning operations) 74780c94ecdSKeith M Wesolowski * Return Values: SUCCESS / FAILURE 74880c94ecdSKeith M Wesolowski * [Success / failure depending upon the outcome of all 74980c94ecdSKeith M Wesolowski * checks and mapping. If any of them fail, a failure is 75080c94ecdSKeith M Wesolowski * sent back] 75180c94ecdSKeith M Wesolowski */ 75280c94ecdSKeith M Wesolowski static uint8_t 75380c94ecdSKeith M Wesolowski cpqary3_update_ctlrdetails(cpqary3_t *cpqary3p, uint32_t *cleanstatus) 75480c94ecdSKeith M Wesolowski { 75580c94ecdSKeith M Wesolowski int8_t retvalue; 75680c94ecdSKeith M Wesolowski uint8_t mem_bar0_set = 0; 75780c94ecdSKeith M Wesolowski uint8_t mem_64_bar0_set = 0; 75880c94ecdSKeith M Wesolowski uint8_t mem_bar1_set = 0; 75980c94ecdSKeith M Wesolowski uint8_t mem_64_bar1_set = 0; 76080c94ecdSKeith M Wesolowski int32_t reglen; 76180c94ecdSKeith M Wesolowski uint32_t *regp; 76280c94ecdSKeith M Wesolowski uint32_t mem_bar0 = 0; 76380c94ecdSKeith M Wesolowski uint32_t mem_64_bar0; 76480c94ecdSKeith M Wesolowski uint32_t mem_bar1 = 0; 76580c94ecdSKeith M Wesolowski uint32_t mem_64_bar1 = 0; 76680c94ecdSKeith M Wesolowski uint32_t ct_mem_bar = 0; 76780c94ecdSKeith M Wesolowski uint32_t ct_cfgmem_val = 0; 76880c94ecdSKeith M Wesolowski uint32_t ct_memoff_val = 0; 76980c94ecdSKeith M Wesolowski uint32_t ct_cfg_bar = 0; 77080c94ecdSKeith M Wesolowski uint32_t ct_mem_len = 0; 77180c94ecdSKeith M Wesolowski offset_t map_len = 0; 77280c94ecdSKeith M Wesolowski uint32_t regset_index; 77380c94ecdSKeith M Wesolowski ddi_acc_handle_t pci_handle; 77480c94ecdSKeith M Wesolowski uint32_t *ct_cfg_offset; 77580c94ecdSKeith M Wesolowski ddi_acc_handle_t ct_cfgoff_handle; 77680c94ecdSKeith M Wesolowski uint32_t *ct_mem_offset; 77780c94ecdSKeith M Wesolowski ddi_acc_handle_t ct_memoff_handle; 77880c94ecdSKeith M Wesolowski 77980c94ecdSKeith M Wesolowski RETURN_FAILURE_IF_NULL(cpqary3p); 78080c94ecdSKeith M Wesolowski 78180c94ecdSKeith M Wesolowski /* 78280c94ecdSKeith M Wesolowski * Check if the bus, or part of the bus that the device is installed 78380c94ecdSKeith M Wesolowski * on, permits the device to become a DMA master. 78480c94ecdSKeith M Wesolowski * If our device is not permitted to become master, return 78580c94ecdSKeith M Wesolowski */ 78680c94ecdSKeith M Wesolowski if (ddi_slaveonly(cpqary3p->dip) == DDI_SUCCESS) 78780c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 78880c94ecdSKeith M Wesolowski 78980c94ecdSKeith M Wesolowski /* 79080c94ecdSKeith M Wesolowski * Get the HW Configuration 79180c94ecdSKeith M Wesolowski * Get Bus #, Dev # and Func # for this device 79280c94ecdSKeith M Wesolowski * Free the memory that regp points towards after the 79380c94ecdSKeith M Wesolowski * ddi_getlongprop() call 79480c94ecdSKeith M Wesolowski */ 79580c94ecdSKeith M Wesolowski if (ddi_getlongprop(DDI_DEV_T_NONE, cpqary3p->dip, DDI_PROP_DONTPASS, 79680c94ecdSKeith M Wesolowski "reg", (caddr_t)®p, ®len) != DDI_PROP_SUCCESS) 79780c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 79880c94ecdSKeith M Wesolowski 79980c94ecdSKeith M Wesolowski cpqary3p->bus = PCI_REG_BUS_G(*regp); 80080c94ecdSKeith M Wesolowski cpqary3p->dev = PCI_REG_DEV_G(*regp); 80180c94ecdSKeith M Wesolowski cpqary3p->fun = PCI_REG_FUNC_G(*regp); 80280c94ecdSKeith M Wesolowski 80380c94ecdSKeith M Wesolowski for (regset_index = 0; regset_index < reglen / 20; regset_index ++) { 80480c94ecdSKeith M Wesolowski if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x2) { 80580c94ecdSKeith M Wesolowski if (!mem_bar0_set) { 80680c94ecdSKeith M Wesolowski mem_bar0 = regset_index; 80780c94ecdSKeith M Wesolowski mem_bar0_set = 1; 80880c94ecdSKeith M Wesolowski } else if (!mem_bar1_set) { 80980c94ecdSKeith M Wesolowski mem_bar1 = regset_index; 81080c94ecdSKeith M Wesolowski mem_bar1_set = 1; 81180c94ecdSKeith M Wesolowski } 81280c94ecdSKeith M Wesolowski } 81380c94ecdSKeith M Wesolowski } 81480c94ecdSKeith M Wesolowski 81580c94ecdSKeith M Wesolowski mem_64_bar0 = mem_bar0; 81680c94ecdSKeith M Wesolowski mem_64_bar1 = mem_bar1; 81780c94ecdSKeith M Wesolowski 81880c94ecdSKeith M Wesolowski for (regset_index = 0; regset_index < reglen / 20; regset_index ++) { 81980c94ecdSKeith M Wesolowski if (PCI_REG_ADDR_G(*(regp + regset_index * 5)) == 0x3) { 82080c94ecdSKeith M Wesolowski if (!mem_64_bar0_set) { 82180c94ecdSKeith M Wesolowski mem_64_bar0 = regset_index; 82280c94ecdSKeith M Wesolowski mem_64_bar0_set = 1; 82380c94ecdSKeith M Wesolowski } else if (!mem_64_bar1_set) { 82480c94ecdSKeith M Wesolowski mem_64_bar1 = regset_index; 82580c94ecdSKeith M Wesolowski mem_64_bar1_set = 1; 82680c94ecdSKeith M Wesolowski } 82780c94ecdSKeith M Wesolowski } 82880c94ecdSKeith M Wesolowski } 82980c94ecdSKeith M Wesolowski 83080c94ecdSKeith M Wesolowski mem_bar0 = mem_64_bar0; 83180c94ecdSKeith M Wesolowski mem_bar1 = mem_64_bar1; 83280c94ecdSKeith M Wesolowski 83380c94ecdSKeith M Wesolowski MEM_SFREE(regp, reglen); 83480c94ecdSKeith M Wesolowski 83580c94ecdSKeith M Wesolowski /* 83680c94ecdSKeith M Wesolowski * Setup resources to access the Local PCI Bus 83780c94ecdSKeith M Wesolowski * If unsuccessful, return. 83880c94ecdSKeith M Wesolowski * Else, read the following from the PCI space: 83980c94ecdSKeith M Wesolowski * Sub-System Vendor ID 84080c94ecdSKeith M Wesolowski * Sub-System Device ID 84180c94ecdSKeith M Wesolowski * Interrupt Line 84280c94ecdSKeith M Wesolowski * Command Register 84380c94ecdSKeith M Wesolowski * Free the just allocated resources. 84480c94ecdSKeith M Wesolowski */ 84580c94ecdSKeith M Wesolowski if (pci_config_setup(cpqary3p->dip, &pci_handle) != DDI_SUCCESS) 84680c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 84780c94ecdSKeith M Wesolowski 84880c94ecdSKeith M Wesolowski cpqary3p->irq = pci_config_get8(pci_handle, PCI_CONF_ILINE); 84980c94ecdSKeith M Wesolowski cpqary3p->board_id = 85080c94ecdSKeith M Wesolowski (pci_config_get16(pci_handle, PCI_CONF_SUBVENID) << 16) 85180c94ecdSKeith M Wesolowski | pci_config_get16(pci_handle, PCI_CONF_SUBSYSID); 85280c94ecdSKeith M Wesolowski 85380c94ecdSKeith M Wesolowski pci_config_teardown(&pci_handle); 85480c94ecdSKeith M Wesolowski 85580c94ecdSKeith M Wesolowski /* 85680c94ecdSKeith M Wesolowski * Verify Board Id 85780c94ecdSKeith M Wesolowski * If unsupported boards are detected, return. 85880c94ecdSKeith M Wesolowski * Update name for controller for driver use. 85980c94ecdSKeith M Wesolowski */ 86080c94ecdSKeith M Wesolowski cpqary3p->bddef = cpqary3_bd_getbybid(cpqary3p->board_id); 86180c94ecdSKeith M Wesolowski if (cpqary3p->bddef == NULL) { 86280c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 86380c94ecdSKeith M Wesolowski "CPQary3: <Bid 0x%X> Controller NOT Supported", 86480c94ecdSKeith M Wesolowski cpqary3p->board_id); 86580c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 86680c94ecdSKeith M Wesolowski } 86780c94ecdSKeith M Wesolowski map_len = cpqary3p->bddef->bd_maplen; 86880c94ecdSKeith M Wesolowski (void) strcpy(cpqary3p->hba_name, cpqary3p->bddef->bd_dispname); 86980c94ecdSKeith M Wesolowski 87080c94ecdSKeith M Wesolowski /* 87180c94ecdSKeith M Wesolowski * Set up a mapping for the following registers: 87280c94ecdSKeith M Wesolowski * Inbound Doorbell 87380c94ecdSKeith M Wesolowski * Outbound List Status 87480c94ecdSKeith M Wesolowski * Outbound Interrupt Mask 87580c94ecdSKeith M Wesolowski * Host Inbound Queue 87680c94ecdSKeith M Wesolowski * Host Outbound Queue 87780c94ecdSKeith M Wesolowski * Host Transport Configuration Table 87880c94ecdSKeith M Wesolowski * Mapping of the above has been done in that order. 87980c94ecdSKeith M Wesolowski */ 88080c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 88180c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 88280c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->idr, (offset_t)I2O_IBDB_SET, map_len, 88380c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->idr_handle); 88480c94ecdSKeith M Wesolowski 88580c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 88680c94ecdSKeith M Wesolowski if (DDI_REGS_ACC_CONFLICT == retvalue) { 88780c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 88880c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 88980c94ecdSKeith M Wesolowski } 89080c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Inbound Doorbell " 89180c94ecdSKeith M Wesolowski "Register Mapping Failed"); 89280c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 89380c94ecdSKeith M Wesolowski } 89480c94ecdSKeith M Wesolowski 89580c94ecdSKeith M Wesolowski /* PERF */ 89680c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 89780c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 89880c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->odr, (offset_t)I2O_OBDB_STATUS, map_len, 89980c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->odr_handle); 90080c94ecdSKeith M Wesolowski 90180c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 90280c94ecdSKeith M Wesolowski if (DDI_REGS_ACC_CONFLICT == retvalue) { 90380c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 90480c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 90580c94ecdSKeith M Wesolowski } 90680c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 90780c94ecdSKeith M Wesolowski "CPQary3 : Outbound Doorbell Register Mapping Failed"); 90880c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 90980c94ecdSKeith M Wesolowski } 91080c94ecdSKeith M Wesolowski 91180c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 91280c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 91380c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->odr_cl, (offset_t)I2O_OBDB_CLEAR, map_len, 91480c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->odr_cl_handle); 91580c94ecdSKeith M Wesolowski 91680c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 91780c94ecdSKeith M Wesolowski if (DDI_REGS_ACC_CONFLICT == retvalue) { 91880c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 91980c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 92080c94ecdSKeith M Wesolowski } 92180c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Outbound Doorbell " 92280c94ecdSKeith M Wesolowski "Register Clear Mapping Failed"); 92380c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 92480c94ecdSKeith M Wesolowski } 92580c94ecdSKeith M Wesolowski 92680c94ecdSKeith M Wesolowski /* LOCKUP CODE */ 92780c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 92880c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 92980c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->spr0, (offset_t)I2O_CTLR_INIT, map_len, 93080c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->spr0_handle); 93180c94ecdSKeith M Wesolowski 93280c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 93380c94ecdSKeith M Wesolowski if (DDI_REGS_ACC_CONFLICT == retvalue) { 93480c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 93580c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 93680c94ecdSKeith M Wesolowski } 93780c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 93880c94ecdSKeith M Wesolowski "CPQary3 : Scratch Pad register zero Mapping Failed"); 93980c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 94080c94ecdSKeith M Wesolowski } 94180c94ecdSKeith M Wesolowski /* LOCKUP CODE */ 94280c94ecdSKeith M Wesolowski /* PERF */ 94380c94ecdSKeith M Wesolowski 94480c94ecdSKeith M Wesolowski *cleanstatus |= CPQARY3_MEM_MAPPED; 94580c94ecdSKeith M Wesolowski 94680c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 94780c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 94880c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->isr, (offset_t)I2O_INT_STATUS, map_len, 94980c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->isr_handle); 95080c94ecdSKeith M Wesolowski 95180c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 95280c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 95380c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 95480c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 95580c94ecdSKeith M Wesolowski } 95680c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 95780c94ecdSKeith M Wesolowski "CPQary3 : Interrupt Status Register Mapping Failed"); 95880c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 95980c94ecdSKeith M Wesolowski } 96080c94ecdSKeith M Wesolowski 96180c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 96280c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 96380c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->imr, (offset_t)I2O_INT_MASK, map_len, 96480c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->imr_handle); 96580c94ecdSKeith M Wesolowski 96680c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 96780c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 96880c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 96980c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 97080c94ecdSKeith M Wesolowski } 97180c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 97280c94ecdSKeith M Wesolowski "CPQary3 : Interrupt Mask Register Mapping Failed"); 97380c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 97480c94ecdSKeith M Wesolowski } 97580c94ecdSKeith M Wesolowski 97680c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 97780c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 97880c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->ipq, (offset_t)I2O_IBPOST_Q, map_len, 97980c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &cpqary3p->ipq_handle); 98080c94ecdSKeith M Wesolowski 98180c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 98280c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 98380c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 98480c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 98580c94ecdSKeith M Wesolowski } 98680c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 98780c94ecdSKeith M Wesolowski "CPQary3 : Inbound Queue Register Mapping Failed"); 98880c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 98980c94ecdSKeith M Wesolowski } 99080c94ecdSKeith M Wesolowski 99180c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 99280c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&cpqary3p->opq, 99380c94ecdSKeith M Wesolowski (offset_t)I2O_OBPOST_Q, map_len, &cpqary3_dev_attributes, 99480c94ecdSKeith M Wesolowski &cpqary3p->opq_handle); 99580c94ecdSKeith M Wesolowski 99680c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 99780c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 99880c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 99980c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 100080c94ecdSKeith M Wesolowski } 100180c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Outbound Post Queue " 100280c94ecdSKeith M Wesolowski "Register Mapping Failed"); 100380c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 100480c94ecdSKeith M Wesolowski } 100580c94ecdSKeith M Wesolowski 100680c94ecdSKeith M Wesolowski 100780c94ecdSKeith M Wesolowski /* 100880c94ecdSKeith M Wesolowski * The config offset and memory offset have to be obtained in order to 100980c94ecdSKeith M Wesolowski * locate the config table. 101080c94ecdSKeith M Wesolowski */ 101180c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 101280c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ (caddr_t *)&ct_cfg_offset, 101380c94ecdSKeith M Wesolowski (offset_t)CT_CFG_OFFSET, map_len, &cpqary3_dev_attributes, 101480c94ecdSKeith M Wesolowski &ct_cfgoff_handle); 101580c94ecdSKeith M Wesolowski 101680c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 101780c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 101880c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 101980c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 102080c94ecdSKeith M Wesolowski } 102180c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Configuration Table " 102280c94ecdSKeith M Wesolowski "Register Mapping Failed"); 102380c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 102480c94ecdSKeith M Wesolowski } 102580c94ecdSKeith M Wesolowski 102680c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 102780c94ecdSKeith M Wesolowski mem_bar0, /* INDEX_PCI_BASE0, */ 102880c94ecdSKeith M Wesolowski (caddr_t *)&ct_mem_offset, (offset_t)CT_MEM_OFFSET, map_len, 102980c94ecdSKeith M Wesolowski &cpqary3_dev_attributes, &ct_memoff_handle); 103080c94ecdSKeith M Wesolowski 103180c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 103280c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 103380c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 103480c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 103580c94ecdSKeith M Wesolowski } 103680c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Configuration Table " 103780c94ecdSKeith M Wesolowski "Register Mapping Failed"); 103880c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 103980c94ecdSKeith M Wesolowski } 104080c94ecdSKeith M Wesolowski 104180c94ecdSKeith M Wesolowski ct_cfgmem_val = (uint32_t)ddi_get32(ct_cfgoff_handle, ct_cfg_offset); 104280c94ecdSKeith M Wesolowski ct_memoff_val = (uint32_t)ddi_get32(ct_memoff_handle, ct_mem_offset); 104380c94ecdSKeith M Wesolowski 104480c94ecdSKeith M Wesolowski ddi_regs_map_free(&ct_cfgoff_handle); 104580c94ecdSKeith M Wesolowski ddi_regs_map_free(&ct_memoff_handle); 104680c94ecdSKeith M Wesolowski 104780c94ecdSKeith M Wesolowski ct_cfg_bar = (ct_cfgmem_val & 0x0000ffff); 104880c94ecdSKeith M Wesolowski ct_mem_len = (ct_cfgmem_val & 0xffff0000); 104980c94ecdSKeith M Wesolowski ct_mem_len = (ct_mem_len >> 16); 105080c94ecdSKeith M Wesolowski 105180c94ecdSKeith M Wesolowski if (ct_cfg_bar == 0x10) { 105280c94ecdSKeith M Wesolowski if (ct_mem_len) { 105380c94ecdSKeith M Wesolowski ct_mem_bar = mem_64_bar0; 105480c94ecdSKeith M Wesolowski } else { 105580c94ecdSKeith M Wesolowski ct_mem_bar = mem_bar0; 105680c94ecdSKeith M Wesolowski } 105780c94ecdSKeith M Wesolowski 105880c94ecdSKeith M Wesolowski } else if (ct_cfg_bar == 0x14) { 105980c94ecdSKeith M Wesolowski if (ct_mem_len) { 106080c94ecdSKeith M Wesolowski ct_mem_bar = mem_64_bar1; 106180c94ecdSKeith M Wesolowski } else { 106280c94ecdSKeith M Wesolowski ct_mem_bar = mem_bar1; 106380c94ecdSKeith M Wesolowski } 106480c94ecdSKeith M Wesolowski } else { 106580c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 106680c94ecdSKeith M Wesolowski } 106780c94ecdSKeith M Wesolowski 106880c94ecdSKeith M Wesolowski 106980c94ecdSKeith M Wesolowski /* 107080c94ecdSKeith M Wesolowski * The Configuration Table(CT) shall be mapped in the form of a 107180c94ecdSKeith M Wesolowski * structure since several members in the CT need to be accessed 107280c94ecdSKeith M Wesolowski * to read and write. 107380c94ecdSKeith M Wesolowski */ 107480c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 107580c94ecdSKeith M Wesolowski ct_mem_bar, /* INDEX_PCI_BASE0/1, */ 107680c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->ct, (offset_t)ct_memoff_val, 107780c94ecdSKeith M Wesolowski sizeof (CfgTable_t), &cpqary3_dev_attributes, &cpqary3p->ct_handle); 107880c94ecdSKeith M Wesolowski 107980c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 108080c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) { 108180c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 108280c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 108380c94ecdSKeith M Wesolowski } 108480c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Configuration Table " 108580c94ecdSKeith M Wesolowski "Register Mapping Failed"); 108680c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 108780c94ecdSKeith M Wesolowski } 108880c94ecdSKeith M Wesolowski 108980c94ecdSKeith M Wesolowski /* PERF */ 109080c94ecdSKeith M Wesolowski 109180c94ecdSKeith M Wesolowski retvalue = ddi_regs_map_setup(cpqary3p->dip, 109280c94ecdSKeith M Wesolowski ct_mem_bar, /* INDEX_PCI_BASE0/1, */ 109380c94ecdSKeith M Wesolowski (caddr_t *)&cpqary3p->cp, 109480c94ecdSKeith M Wesolowski (offset_t)(ct_memoff_val + cpqary3p->ct->TransportMethodOffset), 109580c94ecdSKeith M Wesolowski sizeof (CfgTrans_Perf_t), &cpqary3_dev_attributes, 109680c94ecdSKeith M Wesolowski &cpqary3p->cp_handle); 109780c94ecdSKeith M Wesolowski 109880c94ecdSKeith M Wesolowski if (retvalue != DDI_SUCCESS) { 109980c94ecdSKeith M Wesolowski if (retvalue == DDI_REGS_ACC_CONFLICT) 110080c94ecdSKeith M Wesolowski cmn_err(CE_WARN, 110180c94ecdSKeith M Wesolowski "CPQary3 : Registers Mapping Conflict"); 110280c94ecdSKeith M Wesolowski cmn_err(CE_WARN, "CPQary3 : Performant Transport Method Table " 110380c94ecdSKeith M Wesolowski "Mapping Failed"); 110480c94ecdSKeith M Wesolowski return (CPQARY3_FAILURE); 110580c94ecdSKeith M Wesolowski } 110680c94ecdSKeith M Wesolowski 110780c94ecdSKeith M Wesolowski /* PERF */ 110880c94ecdSKeith M Wesolowski 110980c94ecdSKeith M Wesolowski return (CPQARY3_SUCCESS); 111080c94ecdSKeith M Wesolowski } 1111