Deleted Added
full compact
tws_user.c (226026) tws_user.c (241753)
1/*
2 * Copyright (c) 2010, LSI Corp.
3 * All rights reserved.
4 * Author : Manjunath Ranganathaiah
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 17 unchanged lines hidden (view full) ---

26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
1/*
2 * Copyright (c) 2010, LSI Corp.
3 * All rights reserved.
4 * Author : Manjunath Ranganathaiah
5 * Support: freebsdraid@lsi.com
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 17 unchanged lines hidden (view full) ---

26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $FreeBSD: head/sys/dev/tws/tws_user.c 226026 2011-10-04 21:40:25Z delphij $
34 * $FreeBSD: head/sys/dev/tws/tws_user.c 241753 2012-10-19 22:07:40Z delphij $
35 */
36
37#include <dev/tws/tws.h>
38#include <dev/tws/tws_services.h>
39#include <dev/tws/tws_hdm.h>
40#include <dev/tws/tws_user.h>
41
42

--- 46 unchanged lines hidden (view full) ---

89static int
90tws_passthru(struct tws_softc *sc, void *buf)
91{
92 struct tws_request *req;
93 struct tws_ioctl_no_data_buf *ubuf = (struct tws_ioctl_no_data_buf *)buf;
94 int error;
95 u_int16_t lun4;
96
35 */
36
37#include <dev/tws/tws.h>
38#include <dev/tws/tws_services.h>
39#include <dev/tws/tws_hdm.h>
40#include <dev/tws/tws_user.h>
41
42

--- 46 unchanged lines hidden (view full) ---

89static int
90tws_passthru(struct tws_softc *sc, void *buf)
91{
92 struct tws_request *req;
93 struct tws_ioctl_no_data_buf *ubuf = (struct tws_ioctl_no_data_buf *)buf;
94 int error;
95 u_int16_t lun4;
96
97
97 if ( tws_get_state(sc) != TWS_ONLINE) {
98 return(EBUSY);
99 }
100
98 if ( tws_get_state(sc) != TWS_ONLINE) {
99 return(EBUSY);
100 }
101
102 //==============================================================================================
103 // Get a command
104 //
101 do {
102 req = tws_get_request(sc, TWS_REQ_TYPE_PASSTHRU);
103 if ( !req ) {
105 do {
106 req = tws_get_request(sc, TWS_REQ_TYPE_PASSTHRU);
107 if ( !req ) {
104 sc->chan = 1;
105 error = tsleep((void *)&sc->chan, 0,
106 "tws_sleep", TWS_IOCTL_TIMEOUT*hz);
108 sc->chan = (void *)sc;
109 error = tsleep(sc->chan, 0, "tws_sleep", TWS_IOCTL_TIMEOUT*hz);
107 if ( error == EWOULDBLOCK ) {
108 return(ETIMEDOUT);
109 }
110 } else {
110 if ( error == EWOULDBLOCK ) {
111 return(ETIMEDOUT);
112 }
113 } else {
114 // Make sure we are still ready for new commands...
115 if ( tws_get_state(sc) != TWS_ONLINE) {
116 return(EBUSY);
117 }
111 break;
112 }
118 break;
119 }
113 }while(1);
120 } while(1);
114
121
115 req->length = ubuf->driver_pkt.buffer_length;
122 req->length = (ubuf->driver_pkt.buffer_length + 511) & ~511;
116 TWS_TRACE_DEBUG(sc, "datal,rid", req->length, req->request_id);
117 if ( req->length ) {
123 TWS_TRACE_DEBUG(sc, "datal,rid", req->length, req->request_id);
124 if ( req->length ) {
118 req->data = malloc(req->length, M_TWS, M_WAITOK | M_ZERO);
119 if ( !req->data ) {
120 TWS_TRACE_DEBUG(sc, "malloc failed", 0, req->request_id);
121 req->state = TWS_REQ_STATE_FREE;
122 ubuf->driver_pkt.os_status = ENOMEM;
123 if ( sc->chan ) {
124 sc->chan = 0;
125 wakeup_one((void *)&sc->chan);
126 }
127 return(ENOMEM);
128 }
129 bzero(req->data, req->length);
125 req->data = sc->ioctl_data_mem;
126 req->dma_map = sc->ioctl_data_map;
127
128 //==========================================================================================
129 // Copy data in from user space
130 //
130 error = copyin(ubuf->pdata, req->data, req->length);
131 }
131 error = copyin(ubuf->pdata, req->data, req->length);
132 }
133
134 //==============================================================================================
135 // Set command fields
136 //
132 req->flags = TWS_DIR_IN | TWS_DIR_OUT;
133 req->cb = tws_passthru_complete;
134
135 memcpy(&req->cmd_pkt->cmd, &ubuf->cmd_pkt.cmd,
136 sizeof(struct tws_command_apache));
137
138 if ( GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) ==
139 TWS_FW_CMD_EXECUTE_SCSI ) {
140 lun4 = req->cmd_pkt->cmd.pkt_a.lun_l4__req_id & 0xF000;
141 req->cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun4 | req->request_id;
142 } else {
143 req->cmd_pkt->cmd.pkt_g.generic.request_id = (u_int8_t) req->request_id;
137 req->flags = TWS_DIR_IN | TWS_DIR_OUT;
138 req->cb = tws_passthru_complete;
139
140 memcpy(&req->cmd_pkt->cmd, &ubuf->cmd_pkt.cmd,
141 sizeof(struct tws_command_apache));
142
143 if ( GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) ==
144 TWS_FW_CMD_EXECUTE_SCSI ) {
145 lun4 = req->cmd_pkt->cmd.pkt_a.lun_l4__req_id & 0xF000;
146 req->cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun4 | req->request_id;
147 } else {
148 req->cmd_pkt->cmd.pkt_g.generic.request_id = (u_int8_t) req->request_id;
144
145 }
146
149 }
150
151 //==============================================================================================
152 // Send command to controller
153 //
147 error = tws_map_request(sc, req);
148 if (error) {
149 ubuf->driver_pkt.os_status = error;
154 error = tws_map_request(sc, req);
155 if (error) {
156 ubuf->driver_pkt.os_status = error;
150 goto out;
157 goto out_data;
151 }
152
158 }
159
153//==================================================================================================
160 if ( req->state == TWS_REQ_STATE_COMPLETE ) {
161 ubuf->driver_pkt.os_status = req->error_code;
162 goto out_unmap;
163 }
164
154 mtx_lock(&sc->gen_lock);
155 error = mtx_sleep(req, &sc->gen_lock, 0, "tws_passthru", TWS_IOCTL_TIMEOUT*hz);
156 mtx_unlock(&sc->gen_lock);
157 if (( req->state != TWS_REQ_STATE_COMPLETE ) && ( error == EWOULDBLOCK )) {
158 TWS_TRACE_DEBUG(sc, "msleep timeout", error, req->request_id);
159 tws_timeout((void*) req);
160 }
161
165 mtx_lock(&sc->gen_lock);
166 error = mtx_sleep(req, &sc->gen_lock, 0, "tws_passthru", TWS_IOCTL_TIMEOUT*hz);
167 mtx_unlock(&sc->gen_lock);
168 if (( req->state != TWS_REQ_STATE_COMPLETE ) && ( error == EWOULDBLOCK )) {
169 TWS_TRACE_DEBUG(sc, "msleep timeout", error, req->request_id);
170 tws_timeout((void*) req);
171 }
172
173out_unmap:
162 if ( req->error_code == TWS_REQ_RET_RESET ) {
163 error = EBUSY;
164 req->error_code = EBUSY;
165 TWS_TRACE_DEBUG(sc, "ioctl reset", error, req->request_id);
166 }
167
168 tws_unmap_request(sc, req);
169
174 if ( req->error_code == TWS_REQ_RET_RESET ) {
175 error = EBUSY;
176 req->error_code = EBUSY;
177 TWS_TRACE_DEBUG(sc, "ioctl reset", error, req->request_id);
178 }
179
180 tws_unmap_request(sc, req);
181
182 //==============================================================================================
183 // Return command status to user space
184 //
170 memcpy(&ubuf->cmd_pkt.hdr, &req->cmd_pkt->hdr, sizeof(struct tws_command_apache));
171 memcpy(&ubuf->cmd_pkt.cmd, &req->cmd_pkt->cmd, sizeof(struct tws_command_apache));
185 memcpy(&ubuf->cmd_pkt.hdr, &req->cmd_pkt->hdr, sizeof(struct tws_command_apache));
186 memcpy(&ubuf->cmd_pkt.cmd, &req->cmd_pkt->cmd, sizeof(struct tws_command_apache));
172 if ( !error && req->length ) {
173 error = copyout(req->data, ubuf->pdata, req->length);
187
188out_data:
189 if ( req->length ) {
190 //==========================================================================================
191 // Copy data out to user space
192 //
193 if ( !error )
194 error = copyout(req->data, ubuf->pdata, ubuf->driver_pkt.buffer_length);
174 }
195 }
175//==================================================================================================
176
196
177out:
178 free(req->data, M_TWS);
179
180 if ( error )
181 TWS_TRACE_DEBUG(sc, "errored", error, 0);
182
183 if ( req->error_code != TWS_REQ_RET_SUBMIT_SUCCESS )
184 ubuf->driver_pkt.os_status = error;
185
197 if ( error )
198 TWS_TRACE_DEBUG(sc, "errored", error, 0);
199
200 if ( req->error_code != TWS_REQ_RET_SUBMIT_SUCCESS )
201 ubuf->driver_pkt.os_status = error;
202
203 //==============================================================================================
204 // Free command
205 //
186 req->state = TWS_REQ_STATE_FREE;
187
206 req->state = TWS_REQ_STATE_FREE;
207
188 if ( sc->chan && (tws_get_state(sc) == TWS_ONLINE) ) {
189 sc->chan = 0;
190 wakeup_one((void *)&sc->chan);
191 }
208 wakeup_one(sc->chan);
209
192 return(error);
193}
194
195void
196tws_passthru_complete(struct tws_request *req)
197{
198 req->state = TWS_REQ_STATE_COMPLETE;
199 wakeup_one(req);

--- 180 unchanged lines hidden ---
210 return(error);
211}
212
213void
214tws_passthru_complete(struct tws_request *req)
215{
216 req->state = TWS_REQ_STATE_COMPLETE;
217 wakeup_one(req);

--- 180 unchanged lines hidden ---