isci: uplevel register hardware data structures and unsolicited frame handling
[linux-2.6.git] / drivers / scsi / isci / phy.c
1 /*
2  * This file is provided under a dual BSD/GPLv2 license.  When using or
3  * redistributing this file, you may do so under either license.
4  *
5  * GPL LICENSE SUMMARY
6  *
7  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of version 2 of the GNU General Public License as
11  * published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
24  * BSD LICENSE
25  *
26  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
27  * All rights reserved.
28  *
29  * Redistribution and use in source and binary forms, with or without
30  * modification, are permitted provided that the following conditions
31  * are met:
32  *
33  *   * Redistributions of source code must retain the above copyright
34  *     notice, this list of conditions and the following disclaimer.
35  *   * Redistributions in binary form must reproduce the above copyright
36  *     notice, this list of conditions and the following disclaimer in
37  *     the documentation and/or other materials provided with the
38  *     distribution.
39  *   * Neither the name of Intel Corporation nor the names of its
40  *     contributors may be used to endorse or promote products derived
41  *     from this software without specific prior written permission.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  */
55
56 #include "isci.h"
57 #include "host.h"
58 #include "phy.h"
59 #include "scic_port.h"
60 #include "scic_config_parameters.h"
61
62 struct scic_sds_phy;
63 extern enum sci_status scic_sds_phy_start(struct scic_sds_phy *sci_phy);
64 extern enum sci_status scic_sds_phy_stop(struct scic_sds_phy *sci_phy);
65
66 void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index)
67 {
68         union scic_oem_parameters oem;
69         u64 sci_sas_addr;
70         __be64 sas_addr;
71
72         scic_oem_parameters_get(&ihost->sci, &oem);
73         sci_sas_addr = oem.sds1.phys[index].sas_address.high;
74         sci_sas_addr <<= 32;
75         sci_sas_addr |= oem.sds1.phys[index].sas_address.low;
76         sas_addr = cpu_to_be64(sci_sas_addr);
77         memcpy(iphy->sas_addr, &sas_addr, sizeof(sas_addr));
78
79         iphy->isci_port = NULL;
80         iphy->sas_phy.enabled = 0;
81         iphy->sas_phy.id = index;
82         iphy->sas_phy.sas_addr = &iphy->sas_addr[0];
83         iphy->sas_phy.frame_rcvd = (u8 *)&iphy->frame_rcvd;
84         iphy->sas_phy.ha = &ihost->sas_ha;
85         iphy->sas_phy.lldd_phy = iphy;
86         iphy->sas_phy.enabled = 1;
87         iphy->sas_phy.class = SAS;
88         iphy->sas_phy.iproto = SAS_PROTOCOL_ALL;
89         iphy->sas_phy.tproto = 0;
90         iphy->sas_phy.type = PHY_TYPE_PHYSICAL;
91         iphy->sas_phy.role = PHY_ROLE_INITIATOR;
92         iphy->sas_phy.oob_mode = OOB_NOT_CONNECTED;
93         iphy->sas_phy.linkrate = SAS_LINK_RATE_UNKNOWN;
94         memset(&iphy->frame_rcvd, 0, sizeof(iphy->frame_rcvd));
95 }
96
97
98 /**
99  * isci_phy_control() - This function is one of the SAS Domain Template
100  *    functions. This is a phy management function.
101  * @phy: This parameter specifies the sphy being controlled.
102  * @func: This parameter specifies the phy control function being invoked.
103  * @buf: This parameter is specific to the phy function being invoked.
104  *
105  * status, zero indicates success.
106  */
107 int isci_phy_control(struct asd_sas_phy *sas_phy,
108                      enum phy_func func,
109                      void *buf)
110 {
111         int ret = 0;
112         struct isci_phy *iphy = sas_phy->lldd_phy;
113         struct isci_port *iport = iphy->isci_port;
114         struct isci_host *ihost = sas_phy->ha->lldd_ha;
115         unsigned long flags;
116
117         dev_dbg(&ihost->pdev->dev,
118                 "%s: phy %p; func %d; buf %p; isci phy %p, port %p\n",
119                 __func__, sas_phy, func, buf, iphy, iport);
120
121         switch (func) {
122         case PHY_FUNC_DISABLE:
123                 spin_lock_irqsave(&ihost->scic_lock, flags);
124                 scic_sds_phy_stop(&iphy->sci);
125                 spin_unlock_irqrestore(&ihost->scic_lock, flags);
126                 break;
127
128         case PHY_FUNC_LINK_RESET:
129                 spin_lock_irqsave(&ihost->scic_lock, flags);
130                 scic_sds_phy_stop(&iphy->sci);
131                 scic_sds_phy_start(&iphy->sci);
132                 spin_unlock_irqrestore(&ihost->scic_lock, flags);
133                 break;
134
135         case PHY_FUNC_HARD_RESET:
136                 if (!iport)
137                         return -ENODEV;
138
139                 /* Perform the port reset. */
140                 ret = isci_port_perform_hard_reset(ihost, iport, iphy);
141
142                 break;
143
144         default:
145                 dev_dbg(&ihost->pdev->dev,
146                            "%s: phy %p; func %d NOT IMPLEMENTED!\n",
147                            __func__, sas_phy, func);
148                 ret = -ENOSYS;
149                 break;
150         }
151         return ret;
152 }