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 --- |