1*2908d778SJames Bottomley /* 2*2908d778SJames Bottomley * Aic94xx SAS/SATA DDB management 3*2908d778SJames Bottomley * 4*2908d778SJames Bottomley * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 5*2908d778SJames Bottomley * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 6*2908d778SJames Bottomley * 7*2908d778SJames Bottomley * This file is licensed under GPLv2. 8*2908d778SJames Bottomley * 9*2908d778SJames Bottomley * This file is part of the aic94xx driver. 10*2908d778SJames Bottomley * 11*2908d778SJames Bottomley * The aic94xx driver is free software; you can redistribute it and/or 12*2908d778SJames Bottomley * modify it under the terms of the GNU General Public License as 13*2908d778SJames Bottomley * published by the Free Software Foundation; version 2 of the 14*2908d778SJames Bottomley * License. 15*2908d778SJames Bottomley * 16*2908d778SJames Bottomley * The aic94xx driver is distributed in the hope that it will be useful, 17*2908d778SJames Bottomley * but WITHOUT ANY WARRANTY; without even the implied warranty of 18*2908d778SJames Bottomley * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19*2908d778SJames Bottomley * General Public License for more details. 20*2908d778SJames Bottomley * 21*2908d778SJames Bottomley * You should have received a copy of the GNU General Public License 22*2908d778SJames Bottomley * along with the aic94xx driver; if not, write to the Free Software 23*2908d778SJames Bottomley * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24*2908d778SJames Bottomley * 25*2908d778SJames Bottomley * $Id: //depot/aic94xx/aic94xx_dev.c#21 $ 26*2908d778SJames Bottomley */ 27*2908d778SJames Bottomley 28*2908d778SJames Bottomley #include "aic94xx.h" 29*2908d778SJames Bottomley #include "aic94xx_hwi.h" 30*2908d778SJames Bottomley #include "aic94xx_reg.h" 31*2908d778SJames Bottomley #include "aic94xx_sas.h" 32*2908d778SJames Bottomley 33*2908d778SJames Bottomley #define FIND_FREE_DDB(_ha) find_first_zero_bit((_ha)->hw_prof.ddb_bitmap, \ 34*2908d778SJames Bottomley (_ha)->hw_prof.max_ddbs) 35*2908d778SJames Bottomley #define SET_DDB(_ddb, _ha) set_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 36*2908d778SJames Bottomley #define CLEAR_DDB(_ddb, _ha) clear_bit(_ddb, (_ha)->hw_prof.ddb_bitmap) 37*2908d778SJames Bottomley 38*2908d778SJames Bottomley static inline int asd_get_ddb(struct asd_ha_struct *asd_ha) 39*2908d778SJames Bottomley { 40*2908d778SJames Bottomley unsigned long flags; 41*2908d778SJames Bottomley int ddb, i; 42*2908d778SJames Bottomley 43*2908d778SJames Bottomley spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 44*2908d778SJames Bottomley ddb = FIND_FREE_DDB(asd_ha); 45*2908d778SJames Bottomley if (ddb >= asd_ha->hw_prof.max_ddbs) { 46*2908d778SJames Bottomley ddb = -ENOMEM; 47*2908d778SJames Bottomley spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 48*2908d778SJames Bottomley goto out; 49*2908d778SJames Bottomley } 50*2908d778SJames Bottomley SET_DDB(ddb, asd_ha); 51*2908d778SJames Bottomley spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 52*2908d778SJames Bottomley 53*2908d778SJames Bottomley for (i = 0; i < sizeof(struct asd_ddb_ssp_smp_target_port); i+= 4) 54*2908d778SJames Bottomley asd_ddbsite_write_dword(asd_ha, ddb, i, 0); 55*2908d778SJames Bottomley out: 56*2908d778SJames Bottomley return ddb; 57*2908d778SJames Bottomley } 58*2908d778SJames Bottomley 59*2908d778SJames Bottomley #define INIT_CONN_TAG offsetof(struct asd_ddb_ssp_smp_target_port, init_conn_tag) 60*2908d778SJames Bottomley #define DEST_SAS_ADDR offsetof(struct asd_ddb_ssp_smp_target_port, dest_sas_addr) 61*2908d778SJames Bottomley #define SEND_QUEUE_HEAD offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_head) 62*2908d778SJames Bottomley #define DDB_TYPE offsetof(struct asd_ddb_ssp_smp_target_port, ddb_type) 63*2908d778SJames Bottomley #define CONN_MASK offsetof(struct asd_ddb_ssp_smp_target_port, conn_mask) 64*2908d778SJames Bottomley #define DDB_TARG_FLAGS offsetof(struct asd_ddb_ssp_smp_target_port, flags) 65*2908d778SJames Bottomley #define DDB_TARG_FLAGS2 offsetof(struct asd_ddb_stp_sata_target_port, flags2) 66*2908d778SJames Bottomley #define EXEC_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, exec_queue_tail) 67*2908d778SJames Bottomley #define SEND_QUEUE_TAIL offsetof(struct asd_ddb_ssp_smp_target_port, send_queue_tail) 68*2908d778SJames Bottomley #define SISTER_DDB offsetof(struct asd_ddb_ssp_smp_target_port, sister_ddb) 69*2908d778SJames Bottomley #define MAX_CCONN offsetof(struct asd_ddb_ssp_smp_target_port, max_concurrent_conn) 70*2908d778SJames Bottomley #define NUM_CTX offsetof(struct asd_ddb_ssp_smp_target_port, num_contexts) 71*2908d778SJames Bottomley #define ATA_CMD_SCBPTR offsetof(struct asd_ddb_stp_sata_target_port, ata_cmd_scbptr) 72*2908d778SJames Bottomley #define SATA_TAG_ALLOC_MASK offsetof(struct asd_ddb_stp_sata_target_port, sata_tag_alloc_mask) 73*2908d778SJames Bottomley #define NUM_SATA_TAGS offsetof(struct asd_ddb_stp_sata_target_port, num_sata_tags) 74*2908d778SJames Bottomley #define SATA_STATUS offsetof(struct asd_ddb_stp_sata_target_port, sata_status) 75*2908d778SJames Bottomley #define NCQ_DATA_SCB_PTR offsetof(struct asd_ddb_stp_sata_target_port, ncq_data_scb_ptr) 76*2908d778SJames Bottomley #define ITNL_TIMEOUT offsetof(struct asd_ddb_ssp_smp_target_port, itnl_timeout) 77*2908d778SJames Bottomley 78*2908d778SJames Bottomley static inline void asd_free_ddb(struct asd_ha_struct *asd_ha, int ddb) 79*2908d778SJames Bottomley { 80*2908d778SJames Bottomley unsigned long flags; 81*2908d778SJames Bottomley 82*2908d778SJames Bottomley if (!ddb || ddb >= 0xFFFF) 83*2908d778SJames Bottomley return; 84*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, DDB_TYPE, DDB_TYPE_UNUSED); 85*2908d778SJames Bottomley spin_lock_irqsave(&asd_ha->hw_prof.ddb_lock, flags); 86*2908d778SJames Bottomley CLEAR_DDB(ddb, asd_ha); 87*2908d778SJames Bottomley spin_unlock_irqrestore(&asd_ha->hw_prof.ddb_lock, flags); 88*2908d778SJames Bottomley } 89*2908d778SJames Bottomley 90*2908d778SJames Bottomley static inline void asd_set_ddb_type(struct domain_device *dev) 91*2908d778SJames Bottomley { 92*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 93*2908d778SJames Bottomley int ddb = (int) (unsigned long) dev->lldd_dev; 94*2908d778SJames Bottomley 95*2908d778SJames Bottomley if (dev->dev_type == SATA_PM_PORT) 96*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_PM_PORT); 97*2908d778SJames Bottomley else if (dev->tproto) 98*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha,ddb, DDB_TYPE, DDB_TYPE_TARGET); 99*2908d778SJames Bottomley else 100*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha,ddb,DDB_TYPE,DDB_TYPE_INITIATOR); 101*2908d778SJames Bottomley } 102*2908d778SJames Bottomley 103*2908d778SJames Bottomley static int asd_init_sata_tag_ddb(struct domain_device *dev) 104*2908d778SJames Bottomley { 105*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 106*2908d778SJames Bottomley int ddb, i; 107*2908d778SJames Bottomley 108*2908d778SJames Bottomley ddb = asd_get_ddb(asd_ha); 109*2908d778SJames Bottomley if (ddb < 0) 110*2908d778SJames Bottomley return ddb; 111*2908d778SJames Bottomley 112*2908d778SJames Bottomley for (i = 0; i < sizeof(struct asd_ddb_sata_tag); i += 2) 113*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 114*2908d778SJames Bottomley 115*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 116*2908d778SJames Bottomley SISTER_DDB, ddb); 117*2908d778SJames Bottomley return 0; 118*2908d778SJames Bottomley } 119*2908d778SJames Bottomley 120*2908d778SJames Bottomley static inline int asd_init_sata(struct domain_device *dev) 121*2908d778SJames Bottomley { 122*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 123*2908d778SJames Bottomley int ddb = (int) (unsigned long) dev->lldd_dev; 124*2908d778SJames Bottomley u32 qdepth = 0; 125*2908d778SJames Bottomley int res = 0; 126*2908d778SJames Bottomley 127*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 128*2908d778SJames Bottomley if ((dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM_PORT) && 129*2908d778SJames Bottomley dev->sata_dev.identify_device && 130*2908d778SJames Bottomley dev->sata_dev.identify_device[10] != 0) { 131*2908d778SJames Bottomley u16 w75 = le16_to_cpu(dev->sata_dev.identify_device[75]); 132*2908d778SJames Bottomley u16 w76 = le16_to_cpu(dev->sata_dev.identify_device[76]); 133*2908d778SJames Bottomley 134*2908d778SJames Bottomley if (w76 & 0x100) /* NCQ? */ 135*2908d778SJames Bottomley qdepth = (w75 & 0x1F) + 1; 136*2908d778SJames Bottomley asd_ddbsite_write_dword(asd_ha, ddb, SATA_TAG_ALLOC_MASK, 137*2908d778SJames Bottomley (1<<qdepth)-1); 138*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, NUM_SATA_TAGS, qdepth); 139*2908d778SJames Bottomley } 140*2908d778SJames Bottomley if (dev->dev_type == SATA_DEV || dev->dev_type == SATA_PM || 141*2908d778SJames Bottomley dev->dev_type == SATA_PM_PORT) { 142*2908d778SJames Bottomley struct dev_to_host_fis *fis = (struct dev_to_host_fis *) 143*2908d778SJames Bottomley dev->frame_rcvd; 144*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, SATA_STATUS, fis->status); 145*2908d778SJames Bottomley } 146*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, NCQ_DATA_SCB_PTR, 0xFFFF); 147*2908d778SJames Bottomley if (qdepth > 0) 148*2908d778SJames Bottomley res = asd_init_sata_tag_ddb(dev); 149*2908d778SJames Bottomley return res; 150*2908d778SJames Bottomley } 151*2908d778SJames Bottomley 152*2908d778SJames Bottomley static int asd_init_target_ddb(struct domain_device *dev) 153*2908d778SJames Bottomley { 154*2908d778SJames Bottomley int ddb, i; 155*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 156*2908d778SJames Bottomley u8 flags = 0; 157*2908d778SJames Bottomley 158*2908d778SJames Bottomley ddb = asd_get_ddb(asd_ha); 159*2908d778SJames Bottomley if (ddb < 0) 160*2908d778SJames Bottomley return ddb; 161*2908d778SJames Bottomley 162*2908d778SJames Bottomley dev->lldd_dev = (void *) (unsigned long) ddb; 163*2908d778SJames Bottomley 164*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, 0, DDB_TP_CONN_TYPE); 165*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, 1, 0); 166*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, INIT_CONN_TAG, 0xFFFF); 167*2908d778SJames Bottomley for (i = 0; i < SAS_ADDR_SIZE; i++) 168*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, DEST_SAS_ADDR+i, 169*2908d778SJames Bottomley dev->sas_addr[i]); 170*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_HEAD, 0xFFFF); 171*2908d778SJames Bottomley asd_set_ddb_type(dev); 172*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, CONN_MASK, dev->port->phy_mask); 173*2908d778SJames Bottomley if (dev->port->oob_mode != SATA_OOB_MODE) { 174*2908d778SJames Bottomley flags |= OPEN_REQUIRED; 175*2908d778SJames Bottomley if ((dev->dev_type == SATA_DEV) || 176*2908d778SJames Bottomley (dev->tproto & SAS_PROTO_STP)) { 177*2908d778SJames Bottomley struct smp_resp *rps_resp = &dev->sata_dev.rps_resp; 178*2908d778SJames Bottomley if (rps_resp->frame_type == SMP_RESPONSE && 179*2908d778SJames Bottomley rps_resp->function == SMP_REPORT_PHY_SATA && 180*2908d778SJames Bottomley rps_resp->result == SMP_RESP_FUNC_ACC) { 181*2908d778SJames Bottomley if (rps_resp->rps.affil_valid) 182*2908d778SJames Bottomley flags |= STP_AFFIL_POL; 183*2908d778SJames Bottomley if (rps_resp->rps.affil_supp) 184*2908d778SJames Bottomley flags |= SUPPORTS_AFFIL; 185*2908d778SJames Bottomley } 186*2908d778SJames Bottomley } else { 187*2908d778SJames Bottomley flags |= CONCURRENT_CONN_SUPP; 188*2908d778SJames Bottomley if (!dev->parent && 189*2908d778SJames Bottomley (dev->dev_type == EDGE_DEV || 190*2908d778SJames Bottomley dev->dev_type == FANOUT_DEV)) 191*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 192*2908d778SJames Bottomley 4); 193*2908d778SJames Bottomley else 194*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, MAX_CCONN, 195*2908d778SJames Bottomley dev->pathways); 196*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, NUM_CTX, 1); 197*2908d778SJames Bottomley } 198*2908d778SJames Bottomley } 199*2908d778SJames Bottomley if (dev->dev_type == SATA_PM) 200*2908d778SJames Bottomley flags |= SATA_MULTIPORT; 201*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS, flags); 202*2908d778SJames Bottomley 203*2908d778SJames Bottomley flags = 0; 204*2908d778SJames Bottomley if (dev->tproto & SAS_PROTO_STP) 205*2908d778SJames Bottomley flags |= STP_CL_POL_NO_TX; 206*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, DDB_TARG_FLAGS2, flags); 207*2908d778SJames Bottomley 208*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, EXEC_QUEUE_TAIL, 0xFFFF); 209*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, SEND_QUEUE_TAIL, 0xFFFF); 210*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 211*2908d778SJames Bottomley 212*2908d778SJames Bottomley if (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTO_STP)) { 213*2908d778SJames Bottomley i = asd_init_sata(dev); 214*2908d778SJames Bottomley if (i < 0) { 215*2908d778SJames Bottomley asd_free_ddb(asd_ha, ddb); 216*2908d778SJames Bottomley return i; 217*2908d778SJames Bottomley } 218*2908d778SJames Bottomley } 219*2908d778SJames Bottomley 220*2908d778SJames Bottomley if (dev->dev_type == SAS_END_DEV) { 221*2908d778SJames Bottomley struct sas_end_device *rdev = rphy_to_end_device(dev->rphy); 222*2908d778SJames Bottomley if (rdev->I_T_nexus_loss_timeout > 0) 223*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 224*2908d778SJames Bottomley min(rdev->I_T_nexus_loss_timeout, 225*2908d778SJames Bottomley (u16)ITNL_TIMEOUT_CONST)); 226*2908d778SJames Bottomley else 227*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, ITNL_TIMEOUT, 228*2908d778SJames Bottomley (u16)ITNL_TIMEOUT_CONST); 229*2908d778SJames Bottomley } 230*2908d778SJames Bottomley return 0; 231*2908d778SJames Bottomley } 232*2908d778SJames Bottomley 233*2908d778SJames Bottomley static int asd_init_sata_pm_table_ddb(struct domain_device *dev) 234*2908d778SJames Bottomley { 235*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 236*2908d778SJames Bottomley int ddb, i; 237*2908d778SJames Bottomley 238*2908d778SJames Bottomley ddb = asd_get_ddb(asd_ha); 239*2908d778SJames Bottomley if (ddb < 0) 240*2908d778SJames Bottomley return ddb; 241*2908d778SJames Bottomley 242*2908d778SJames Bottomley for (i = 0; i < 32; i += 2) 243*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, i, 0xFFFF); 244*2908d778SJames Bottomley 245*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, (int) (unsigned long) dev->lldd_dev, 246*2908d778SJames Bottomley SISTER_DDB, ddb); 247*2908d778SJames Bottomley 248*2908d778SJames Bottomley return 0; 249*2908d778SJames Bottomley } 250*2908d778SJames Bottomley 251*2908d778SJames Bottomley #define PM_PORT_FLAGS offsetof(struct asd_ddb_sata_pm_port, pm_port_flags) 252*2908d778SJames Bottomley #define PARENT_DDB offsetof(struct asd_ddb_sata_pm_port, parent_ddb) 253*2908d778SJames Bottomley 254*2908d778SJames Bottomley /** 255*2908d778SJames Bottomley * asd_init_sata_pm_port_ddb -- SATA Port Multiplier Port 256*2908d778SJames Bottomley * dev: pointer to domain device 257*2908d778SJames Bottomley * 258*2908d778SJames Bottomley * For SATA Port Multiplier Ports we need to allocate one SATA Port 259*2908d778SJames Bottomley * Multiplier Port DDB and depending on whether the target on it 260*2908d778SJames Bottomley * supports SATA II NCQ, one SATA Tag DDB. 261*2908d778SJames Bottomley */ 262*2908d778SJames Bottomley static int asd_init_sata_pm_port_ddb(struct domain_device *dev) 263*2908d778SJames Bottomley { 264*2908d778SJames Bottomley int ddb, i, parent_ddb, pmtable_ddb; 265*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 266*2908d778SJames Bottomley u8 flags; 267*2908d778SJames Bottomley 268*2908d778SJames Bottomley ddb = asd_get_ddb(asd_ha); 269*2908d778SJames Bottomley if (ddb < 0) 270*2908d778SJames Bottomley return ddb; 271*2908d778SJames Bottomley 272*2908d778SJames Bottomley asd_set_ddb_type(dev); 273*2908d778SJames Bottomley flags = (dev->sata_dev.port_no << 4) | PM_PORT_SET; 274*2908d778SJames Bottomley asd_ddbsite_write_byte(asd_ha, ddb, PM_PORT_FLAGS, flags); 275*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, SISTER_DDB, 0xFFFF); 276*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, ATA_CMD_SCBPTR, 0xFFFF); 277*2908d778SJames Bottomley asd_init_sata(dev); 278*2908d778SJames Bottomley 279*2908d778SJames Bottomley parent_ddb = (int) (unsigned long) dev->parent->lldd_dev; 280*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, ddb, PARENT_DDB, parent_ddb); 281*2908d778SJames Bottomley pmtable_ddb = asd_ddbsite_read_word(asd_ha, parent_ddb, SISTER_DDB); 282*2908d778SJames Bottomley asd_ddbsite_write_word(asd_ha, pmtable_ddb, dev->sata_dev.port_no,ddb); 283*2908d778SJames Bottomley 284*2908d778SJames Bottomley if (asd_ddbsite_read_byte(asd_ha, ddb, NUM_SATA_TAGS) > 0) { 285*2908d778SJames Bottomley i = asd_init_sata_tag_ddb(dev); 286*2908d778SJames Bottomley if (i < 0) { 287*2908d778SJames Bottomley asd_free_ddb(asd_ha, ddb); 288*2908d778SJames Bottomley return i; 289*2908d778SJames Bottomley } 290*2908d778SJames Bottomley } 291*2908d778SJames Bottomley return 0; 292*2908d778SJames Bottomley } 293*2908d778SJames Bottomley 294*2908d778SJames Bottomley static int asd_init_initiator_ddb(struct domain_device *dev) 295*2908d778SJames Bottomley { 296*2908d778SJames Bottomley return -ENODEV; 297*2908d778SJames Bottomley } 298*2908d778SJames Bottomley 299*2908d778SJames Bottomley /** 300*2908d778SJames Bottomley * asd_init_sata_pm_ddb -- SATA Port Multiplier 301*2908d778SJames Bottomley * dev: pointer to domain device 302*2908d778SJames Bottomley * 303*2908d778SJames Bottomley * For STP and direct-attached SATA Port Multipliers we need 304*2908d778SJames Bottomley * one target port DDB entry and one SATA PM table DDB entry. 305*2908d778SJames Bottomley */ 306*2908d778SJames Bottomley static int asd_init_sata_pm_ddb(struct domain_device *dev) 307*2908d778SJames Bottomley { 308*2908d778SJames Bottomley int res = 0; 309*2908d778SJames Bottomley 310*2908d778SJames Bottomley res = asd_init_target_ddb(dev); 311*2908d778SJames Bottomley if (res) 312*2908d778SJames Bottomley goto out; 313*2908d778SJames Bottomley res = asd_init_sata_pm_table_ddb(dev); 314*2908d778SJames Bottomley if (res) 315*2908d778SJames Bottomley asd_free_ddb(dev->port->ha->lldd_ha, 316*2908d778SJames Bottomley (int) (unsigned long) dev->lldd_dev); 317*2908d778SJames Bottomley out: 318*2908d778SJames Bottomley return res; 319*2908d778SJames Bottomley } 320*2908d778SJames Bottomley 321*2908d778SJames Bottomley int asd_dev_found(struct domain_device *dev) 322*2908d778SJames Bottomley { 323*2908d778SJames Bottomley int res = 0; 324*2908d778SJames Bottomley 325*2908d778SJames Bottomley switch (dev->dev_type) { 326*2908d778SJames Bottomley case SATA_PM: 327*2908d778SJames Bottomley res = asd_init_sata_pm_ddb(dev); 328*2908d778SJames Bottomley break; 329*2908d778SJames Bottomley case SATA_PM_PORT: 330*2908d778SJames Bottomley res = asd_init_sata_pm_port_ddb(dev); 331*2908d778SJames Bottomley break; 332*2908d778SJames Bottomley default: 333*2908d778SJames Bottomley if (dev->tproto) 334*2908d778SJames Bottomley res = asd_init_target_ddb(dev); 335*2908d778SJames Bottomley else 336*2908d778SJames Bottomley res = asd_init_initiator_ddb(dev); 337*2908d778SJames Bottomley } 338*2908d778SJames Bottomley return res; 339*2908d778SJames Bottomley } 340*2908d778SJames Bottomley 341*2908d778SJames Bottomley void asd_dev_gone(struct domain_device *dev) 342*2908d778SJames Bottomley { 343*2908d778SJames Bottomley int ddb, sister_ddb; 344*2908d778SJames Bottomley struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 345*2908d778SJames Bottomley 346*2908d778SJames Bottomley ddb = (int) (unsigned long) dev->lldd_dev; 347*2908d778SJames Bottomley sister_ddb = asd_ddbsite_read_word(asd_ha, ddb, SISTER_DDB); 348*2908d778SJames Bottomley 349*2908d778SJames Bottomley if (sister_ddb != 0xFFFF) 350*2908d778SJames Bottomley asd_free_ddb(asd_ha, sister_ddb); 351*2908d778SJames Bottomley asd_free_ddb(asd_ha, ddb); 352*2908d778SJames Bottomley dev->lldd_dev = NULL; 353*2908d778SJames Bottomley } 354