xref: /freebsd/sys/dev/tws/tws_cam.c (revision 95ee2897)
1db1fda10SXin LI /*
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4db1fda10SXin LI  * Copyright (c) 2010 LSI Corp.
5db1fda10SXin LI  * All rights reserved.
6db1fda10SXin LI  * Author : Manjunath Ranganathaiah <manjunath.ranganathaiah@lsi.com>
7db1fda10SXin LI  *
8db1fda10SXin LI  * Redistribution and use in source and binary forms, with or without
9db1fda10SXin LI  * modification, are permitted provided that the following conditions
10db1fda10SXin LI  * are met:
11db1fda10SXin LI  * 1. Redistributions of source code must retain the above copyright
12db1fda10SXin LI  *    notice, this list of conditions and the following disclaimer.
13db1fda10SXin LI  * 2. Redistributions in binary form must reproduce the above copyright
14db1fda10SXin LI  *    notice, this list of conditions and the following disclaimer in the
15db1fda10SXin LI  *    documentation and/or other materials provided with the distribution.
16db1fda10SXin LI  *
17db1fda10SXin LI  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18db1fda10SXin LI  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19db1fda10SXin LI  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20db1fda10SXin LI  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21db1fda10SXin LI  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22db1fda10SXin LI  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23db1fda10SXin LI  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24db1fda10SXin LI  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25db1fda10SXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26db1fda10SXin LI  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27db1fda10SXin LI  * SUCH DAMAGE.
28db1fda10SXin LI  */
29db1fda10SXin LI 
30db1fda10SXin LI #include <dev/tws/tws.h>
31db1fda10SXin LI #include <dev/tws/tws_services.h>
32db1fda10SXin LI #include <dev/tws/tws_hdm.h>
33db1fda10SXin LI #include <dev/tws/tws_user.h>
34db1fda10SXin LI #include <cam/cam.h>
35db1fda10SXin LI #include <cam/cam_ccb.h>
36db1fda10SXin LI #include <cam/cam_sim.h>
37db1fda10SXin LI #include <cam/cam_xpt_sim.h>
38db1fda10SXin LI #include <cam/cam_debug.h>
39db1fda10SXin LI #include <cam/cam_periph.h>
40db1fda10SXin LI 
41db1fda10SXin LI #include <cam/scsi/scsi_all.h>
42db1fda10SXin LI #include <cam/scsi/scsi_message.h>
43db1fda10SXin LI 
44db1fda10SXin LI static int tws_cam_depth=(TWS_MAX_REQS - TWS_RESERVED_REQS);
45db1fda10SXin LI static char tws_sev_str[5][8]={"","ERROR","WARNING","INFO","DEBUG"};
46db1fda10SXin LI 
47db1fda10SXin LI static void  tws_action(struct cam_sim *sim, union ccb *ccb);
48db1fda10SXin LI static void  tws_poll(struct cam_sim *sim);
49db1fda10SXin LI static void tws_scsi_complete(struct tws_request *req);
50db1fda10SXin LI 
51db1fda10SXin LI void tws_unmap_request(struct tws_softc *sc, struct tws_request *req);
52db1fda10SXin LI int32_t tws_map_request(struct tws_softc *sc, struct tws_request *req);
53db1fda10SXin LI int tws_bus_scan(struct tws_softc *sc);
54db1fda10SXin LI int tws_cam_attach(struct tws_softc *sc);
55db1fda10SXin LI void tws_cam_detach(struct tws_softc *sc);
56db1fda10SXin LI void tws_reset(void *arg);
57db1fda10SXin LI 
58db1fda10SXin LI static void tws_reset_cb(void *arg);
59db1fda10SXin LI static void tws_reinit(void *arg);
60db1fda10SXin LI static int32_t tws_execute_scsi(struct tws_softc *sc, union ccb *ccb);
61db1fda10SXin LI static void tws_freeze_simq(struct tws_softc *sc, struct tws_request *req);
62db1fda10SXin LI static void tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
63db1fda10SXin LI                             int nseg, int error);
64db1fda10SXin LI static void tws_fill_sg_list(struct tws_softc *sc, void *sgl_src,
65db1fda10SXin LI                             void *sgl_dest, u_int16_t num_sgl_entries);
66db1fda10SXin LI static void tws_err_complete(struct tws_softc *sc, u_int64_t mfa);
67db1fda10SXin LI static void tws_scsi_err_complete(struct tws_request *req,
68db1fda10SXin LI                                                struct tws_command_header *hdr);
69db1fda10SXin LI static void tws_passthru_err_complete(struct tws_request *req,
70db1fda10SXin LI                                                struct tws_command_header *hdr);
71db1fda10SXin LI 
72db1fda10SXin LI void tws_timeout(void *arg);
73db1fda10SXin LI static void tws_intr_attn_aen(struct tws_softc *sc);
74db1fda10SXin LI static void tws_intr_attn_error(struct tws_softc *sc);
75db1fda10SXin LI static void tws_intr_resp(struct tws_softc *sc);
76db1fda10SXin LI void tws_intr(void *arg);
77db1fda10SXin LI void tws_cmd_complete(struct tws_request *req);
78db1fda10SXin LI void tws_aen_complete(struct tws_request *req);
79db1fda10SXin LI int tws_send_scsi_cmd(struct tws_softc *sc, int cmd);
80db1fda10SXin LI void tws_getset_param_complete(struct tws_request *req);
81db1fda10SXin LI int tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id,
82db1fda10SXin LI               u_int32_t param_size, void *data);
83db1fda10SXin LI int tws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id,
84db1fda10SXin LI               u_int32_t param_size, void *data);
85db1fda10SXin LI 
86db1fda10SXin LI extern struct tws_request *tws_get_request(struct tws_softc *sc,
87db1fda10SXin LI                                             u_int16_t type);
88db1fda10SXin LI extern void *tws_release_request(struct tws_request *req);
89db1fda10SXin LI extern int tws_submit_command(struct tws_softc *sc, struct tws_request *req);
90db1fda10SXin LI extern boolean tws_get_response(struct tws_softc *sc,
91db1fda10SXin LI                                            u_int16_t *req_id, u_int64_t *mfa);
92db1fda10SXin LI extern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
93db1fda10SXin LI                                 u_int8_t q_type );
94db1fda10SXin LI extern struct tws_request * tws_q_remove_request(struct tws_softc *sc,
95db1fda10SXin LI                                    struct tws_request *req, u_int8_t q_type );
96db1fda10SXin LI extern void tws_send_event(struct tws_softc *sc, u_int8_t event);
97db1fda10SXin LI 
98db1fda10SXin LI extern struct tws_sense *
99db1fda10SXin LI tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa);
100db1fda10SXin LI 
101db1fda10SXin LI extern void tws_fetch_aen(void *arg);
102db1fda10SXin LI extern void tws_disable_db_intr(struct tws_softc *sc);
103db1fda10SXin LI extern void tws_enable_db_intr(struct tws_softc *sc);
104db1fda10SXin LI extern void tws_passthru_complete(struct tws_request *req);
105db1fda10SXin LI extern void tws_aen_synctime_with_host(struct tws_softc *sc);
106db1fda10SXin LI extern void tws_circular_aenq_insert(struct tws_softc *sc,
107db1fda10SXin LI                     struct tws_circular_q *cq, struct tws_event_packet *aen);
108db1fda10SXin LI extern int tws_use_32bit_sgls;
109db1fda10SXin LI extern boolean tws_ctlr_reset(struct tws_softc *sc);
110db1fda10SXin LI extern struct tws_request * tws_q_remove_tail(struct tws_softc *sc,
111db1fda10SXin LI                                                            u_int8_t q_type );
112db1fda10SXin LI extern void tws_turn_off_interrupts(struct tws_softc *sc);
113db1fda10SXin LI extern void tws_turn_on_interrupts(struct tws_softc *sc);
114db1fda10SXin LI extern int tws_init_connect(struct tws_softc *sc, u_int16_t mc);
115db1fda10SXin LI extern void tws_init_obfl_q(struct tws_softc *sc);
116db1fda10SXin LI extern uint8_t tws_get_state(struct tws_softc *sc);
117db1fda10SXin LI extern void tws_assert_soft_reset(struct tws_softc *sc);
118db1fda10SXin LI extern boolean tws_ctlr_ready(struct tws_softc *sc);
119db1fda10SXin LI extern u_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa);
120db1fda10SXin LI extern int tws_setup_intr(struct tws_softc *sc, int irqs);
121db1fda10SXin LI extern int tws_teardown_intr(struct tws_softc *sc);
122db1fda10SXin LI 
123db1fda10SXin LI int
tws_cam_attach(struct tws_softc * sc)124db1fda10SXin LI tws_cam_attach(struct tws_softc *sc)
125db1fda10SXin LI {
126db1fda10SXin LI     struct cam_devq *devq;
127db1fda10SXin LI 
128db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry", 0, sc);
129db1fda10SXin LI     /* Create a device queue for sim */
130db1fda10SXin LI 
131db1fda10SXin LI     /*
132db1fda10SXin LI      * if the user sets cam depth to less than 1
133db1fda10SXin LI      * cam may get confused
134db1fda10SXin LI      */
135db1fda10SXin LI     if ( tws_cam_depth < 1 )
136db1fda10SXin LI         tws_cam_depth = 1;
137db1fda10SXin LI     if ( tws_cam_depth > (tws_queue_depth - TWS_RESERVED_REQS)  )
138db1fda10SXin LI         tws_cam_depth = tws_queue_depth - TWS_RESERVED_REQS;
139db1fda10SXin LI 
140db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "depths,ctlr,cam", tws_queue_depth, tws_cam_depth);
141db1fda10SXin LI 
142db1fda10SXin LI     if ((devq = cam_simq_alloc(tws_cam_depth)) == NULL) {
143db1fda10SXin LI         tws_log(sc, CAM_SIMQ_ALLOC);
144db1fda10SXin LI         return(ENOMEM);
145db1fda10SXin LI     }
146db1fda10SXin LI 
147db1fda10SXin LI    /*
148db1fda10SXin LI     * Create a SIM entry.  Though we can support tws_cam_depth
149db1fda10SXin LI     * simultaneous requests, we claim to be able to handle only
150db1fda10SXin LI     * (tws_cam_depth), so that we always have reserved  requests
151db1fda10SXin LI     * packet available to service ioctls and internal commands.
152db1fda10SXin LI     */
153db1fda10SXin LI     sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc,
154db1fda10SXin LI                       device_get_unit(sc->tws_dev),
155db1fda10SXin LI                       &sc->sim_lock,
156db1fda10SXin LI                       tws_cam_depth, 1, devq);
157db1fda10SXin LI                       /* 1, 1, devq); */
158db1fda10SXin LI     if (sc->sim == NULL) {
159db1fda10SXin LI         cam_simq_free(devq);
160db1fda10SXin LI         tws_log(sc, CAM_SIM_ALLOC);
161db1fda10SXin LI     }
162db1fda10SXin LI     /* Register the bus. */
163db1fda10SXin LI     mtx_lock(&sc->sim_lock);
164db1fda10SXin LI     if (xpt_bus_register(sc->sim,
165db1fda10SXin LI                          sc->tws_dev,
166db1fda10SXin LI                          0) != CAM_SUCCESS) {
167db1fda10SXin LI         cam_sim_free(sc->sim, TRUE); /* passing true will free the devq */
168db1fda10SXin LI         sc->sim = NULL; /* so cam_detach will not try to free it */
169db1fda10SXin LI         mtx_unlock(&sc->sim_lock);
170db1fda10SXin LI         tws_log(sc, TWS_XPT_BUS_REGISTER);
171db1fda10SXin LI         return(ENXIO);
172db1fda10SXin LI     }
173db1fda10SXin LI     if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim),
174db1fda10SXin LI                          CAM_TARGET_WILDCARD,
175db1fda10SXin LI                          CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
176db1fda10SXin LI         xpt_bus_deregister(cam_sim_path(sc->sim));
177db1fda10SXin LI         /* Passing TRUE to cam_sim_free will free the devq as well. */
178db1fda10SXin LI         cam_sim_free(sc->sim, TRUE);
179db1fda10SXin LI         tws_log(sc, TWS_XPT_CREATE_PATH);
180db1fda10SXin LI         mtx_unlock(&sc->sim_lock);
181db1fda10SXin LI         return(ENXIO);
182db1fda10SXin LI     }
183db1fda10SXin LI     mtx_unlock(&sc->sim_lock);
184db1fda10SXin LI 
185db1fda10SXin LI     return(0);
186db1fda10SXin LI }
187db1fda10SXin LI 
188db1fda10SXin LI void
tws_cam_detach(struct tws_softc * sc)189db1fda10SXin LI tws_cam_detach(struct tws_softc *sc)
190db1fda10SXin LI {
191db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry", 0, 0);
192db1fda10SXin LI     mtx_lock(&sc->sim_lock);
193db1fda10SXin LI     if (sc->path)
194db1fda10SXin LI         xpt_free_path(sc->path);
195db1fda10SXin LI     if (sc->sim) {
196db1fda10SXin LI         xpt_bus_deregister(cam_sim_path(sc->sim));
197db1fda10SXin LI         cam_sim_free(sc->sim, TRUE);
198db1fda10SXin LI     }
199db1fda10SXin LI     mtx_unlock(&sc->sim_lock);
200db1fda10SXin LI }
201db1fda10SXin LI 
202db1fda10SXin LI int
tws_bus_scan(struct tws_softc * sc)203db1fda10SXin LI tws_bus_scan(struct tws_softc *sc)
204db1fda10SXin LI {
205db1fda10SXin LI     union ccb       *ccb;
206db1fda10SXin LI 
207db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry", sc, 0);
208db1fda10SXin LI     if (!(sc->sim))
209db1fda10SXin LI         return(ENXIO);
210b9e92e98SAlexander Motin     ccb = xpt_alloc_ccb();
211b9e92e98SAlexander Motin     mtx_lock(&sc->sim_lock);
212e5dfa058SAlexander Motin     if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
213db1fda10SXin LI                   CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
214b9e92e98SAlexander Motin 	mtx_unlock(&sc->sim_lock);
215db1fda10SXin LI         xpt_free_ccb(ccb);
216db1fda10SXin LI         return(EIO);
217db1fda10SXin LI     }
218db1fda10SXin LI     xpt_rescan(ccb);
219b9e92e98SAlexander Motin     mtx_unlock(&sc->sim_lock);
220db1fda10SXin LI     return(0);
221db1fda10SXin LI }
222db1fda10SXin LI 
223db1fda10SXin LI static void
tws_action(struct cam_sim * sim,union ccb * ccb)224db1fda10SXin LI tws_action(struct cam_sim *sim, union ccb *ccb)
225db1fda10SXin LI {
226db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim);
227db1fda10SXin LI 
228db1fda10SXin LI     switch( ccb->ccb_h.func_code ) {
229db1fda10SXin LI         case XPT_SCSI_IO:
230db1fda10SXin LI         {
231db1fda10SXin LI             if ( tws_execute_scsi(sc, ccb) )
232db1fda10SXin LI                 TWS_TRACE_DEBUG(sc, "execute scsi failed", 0, 0);
233db1fda10SXin LI             break;
234db1fda10SXin LI         }
235db1fda10SXin LI         case XPT_ABORT:
236db1fda10SXin LI         {
237db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "abort i/o", 0, 0);
238db1fda10SXin LI             ccb->ccb_h.status = CAM_UA_ABORT;
239db1fda10SXin LI             xpt_done(ccb);
240db1fda10SXin LI             break;
241db1fda10SXin LI         }
242db1fda10SXin LI         case XPT_RESET_BUS:
243db1fda10SXin LI         {
244db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "reset bus", sim, ccb);
245db1fda10SXin LI             break;
246db1fda10SXin LI         }
247db1fda10SXin LI         case XPT_SET_TRAN_SETTINGS:
248db1fda10SXin LI         {
249db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "set tran settings", sim, ccb);
250db1fda10SXin LI             ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
251db1fda10SXin LI             xpt_done(ccb);
252db1fda10SXin LI 
253db1fda10SXin LI             break;
254db1fda10SXin LI         }
255db1fda10SXin LI         case XPT_GET_TRAN_SETTINGS:
256db1fda10SXin LI         {
257db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb);
258db1fda10SXin LI 
259db1fda10SXin LI             ccb->cts.protocol = PROTO_SCSI;
260db1fda10SXin LI             ccb->cts.protocol_version = SCSI_REV_2;
261db1fda10SXin LI             ccb->cts.transport = XPORT_SPI;
262db1fda10SXin LI             ccb->cts.transport_version = 2;
263db1fda10SXin LI 
264db1fda10SXin LI             ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC;
265db1fda10SXin LI             ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
266db1fda10SXin LI             ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
267db1fda10SXin LI             ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
268db1fda10SXin LI             ccb->ccb_h.status = CAM_REQ_CMP;
269db1fda10SXin LI             xpt_done(ccb);
270db1fda10SXin LI 
271db1fda10SXin LI             break;
272db1fda10SXin LI         }
273db1fda10SXin LI         case XPT_CALC_GEOMETRY:
274db1fda10SXin LI         {
275db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "calc geometry(ccb,block-size)", ccb,
276db1fda10SXin LI                                           ccb->ccg.block_size);
277db1fda10SXin LI             cam_calc_geometry(&ccb->ccg, 1/* extended */);
278db1fda10SXin LI             xpt_done(ccb);
279db1fda10SXin LI 
280db1fda10SXin LI             break;
281db1fda10SXin LI         }
282db1fda10SXin LI         case XPT_PATH_INQ:
283db1fda10SXin LI         {
284db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "path inquiry", sim, ccb);
285db1fda10SXin LI             ccb->cpi.version_num = 1;
286db1fda10SXin LI             ccb->cpi.hba_inquiry = 0;
287db1fda10SXin LI             ccb->cpi.target_sprt = 0;
288db1fda10SXin LI             ccb->cpi.hba_misc = 0;
289db1fda10SXin LI             ccb->cpi.hba_eng_cnt = 0;
290db1fda10SXin LI             ccb->cpi.max_target = TWS_MAX_NUM_UNITS;
291db1fda10SXin LI             ccb->cpi.max_lun = TWS_MAX_NUM_LUNS - 1;
292db1fda10SXin LI             ccb->cpi.unit_number = cam_sim_unit(sim);
293db1fda10SXin LI             ccb->cpi.bus_id = cam_sim_bus(sim);
294db1fda10SXin LI             ccb->cpi.initiator_id = TWS_SCSI_INITIATOR_ID;
295db1fda10SXin LI             ccb->cpi.base_transfer_speed = 6000000;
2964195c7deSAlan Somers             strlcpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
2974195c7deSAlan Somers             strlcpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN);
2984195c7deSAlan Somers             strlcpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
299db1fda10SXin LI             ccb->cpi.transport = XPORT_SPI;
300db1fda10SXin LI             ccb->cpi.transport_version = 2;
301db1fda10SXin LI             ccb->cpi.protocol = PROTO_SCSI;
302db1fda10SXin LI             ccb->cpi.protocol_version = SCSI_REV_2;
303db1fda10SXin LI             ccb->cpi.maxio = TWS_MAX_IO_SIZE;
304db1fda10SXin LI             ccb->ccb_h.status = CAM_REQ_CMP;
305db1fda10SXin LI             xpt_done(ccb);
306db1fda10SXin LI 
307db1fda10SXin LI             break;
308db1fda10SXin LI         }
309db1fda10SXin LI         default:
310db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "default", sim, ccb);
311db1fda10SXin LI             ccb->ccb_h.status = CAM_REQ_INVALID;
312db1fda10SXin LI             xpt_done(ccb);
313db1fda10SXin LI             break;
314db1fda10SXin LI     }
315db1fda10SXin LI }
316db1fda10SXin LI 
317db1fda10SXin LI static void
tws_scsi_complete(struct tws_request * req)318db1fda10SXin LI tws_scsi_complete(struct tws_request *req)
319db1fda10SXin LI {
320db1fda10SXin LI     struct tws_softc *sc = req->sc;
321db1fda10SXin LI 
322db1fda10SXin LI     mtx_lock(&sc->q_lock);
323db1fda10SXin LI     tws_q_remove_request(sc, req, TWS_BUSY_Q);
324db1fda10SXin LI     mtx_unlock(&sc->q_lock);
325db1fda10SXin LI 
326166a4e47SJohn Baldwin     callout_stop(&req->timeout);
327db1fda10SXin LI     tws_unmap_request(req->sc, req);
328db1fda10SXin LI 
329db1fda10SXin LI     req->ccb_ptr->ccb_h.status = CAM_REQ_CMP;
330db1fda10SXin LI     mtx_lock(&sc->sim_lock);
331db1fda10SXin LI     xpt_done(req->ccb_ptr);
332db1fda10SXin LI     mtx_unlock(&sc->sim_lock);
333db1fda10SXin LI 
334db1fda10SXin LI     mtx_lock(&sc->q_lock);
335db1fda10SXin LI     tws_q_insert_tail(sc, req, TWS_FREE_Q);
336db1fda10SXin LI     mtx_unlock(&sc->q_lock);
337db1fda10SXin LI }
338db1fda10SXin LI 
339db1fda10SXin LI void
tws_getset_param_complete(struct tws_request * req)340db1fda10SXin LI tws_getset_param_complete(struct tws_request *req)
341db1fda10SXin LI {
342db1fda10SXin LI     struct tws_softc *sc = req->sc;
343db1fda10SXin LI 
344db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "getset complete", req, req->request_id);
345db1fda10SXin LI 
346166a4e47SJohn Baldwin     callout_stop(&req->timeout);
347db1fda10SXin LI     tws_unmap_request(sc, req);
348db1fda10SXin LI 
349db1fda10SXin LI     free(req->data, M_TWS);
350db1fda10SXin LI 
351db1fda10SXin LI     req->state = TWS_REQ_STATE_FREE;
352db1fda10SXin LI }
353db1fda10SXin LI 
354db1fda10SXin LI void
tws_aen_complete(struct tws_request * req)355db1fda10SXin LI tws_aen_complete(struct tws_request *req)
356db1fda10SXin LI {
357db1fda10SXin LI     struct tws_softc *sc = req->sc;
358db1fda10SXin LI     struct tws_command_header *sense;
359db1fda10SXin LI     struct tws_event_packet event;
360db1fda10SXin LI     u_int16_t aen_code=0;
361db1fda10SXin LI 
362db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "aen complete", 0, req->request_id);
363db1fda10SXin LI 
364166a4e47SJohn Baldwin     callout_stop(&req->timeout);
365db1fda10SXin LI     tws_unmap_request(sc, req);
366db1fda10SXin LI 
367db1fda10SXin LI     sense = (struct tws_command_header *)req->data;
368db1fda10SXin LI 
369db1fda10SXin LI     TWS_TRACE_DEBUG(sc,"sense code, key",sense->sense_data[0],
370db1fda10SXin LI                                    sense->sense_data[2]);
371db1fda10SXin LI     TWS_TRACE_DEBUG(sc,"sense rid, seve",sense->header_desc.request_id,
372db1fda10SXin LI                                    sense->status_block.res__severity);
373db1fda10SXin LI     TWS_TRACE_DEBUG(sc,"sense srcnum, error",sense->status_block.srcnum,
374db1fda10SXin LI                                    sense->status_block.error);
375db1fda10SXin LI     TWS_TRACE_DEBUG(sc,"sense shdr, ssense",sense->header_desc.size_header,
376db1fda10SXin LI                                    sense->header_desc.size_sense);
377db1fda10SXin LI 
378db1fda10SXin LI     aen_code = sense->status_block.error;
379db1fda10SXin LI 
380db1fda10SXin LI     switch ( aen_code ) {
381db1fda10SXin LI         case TWS_AEN_SYNC_TIME_WITH_HOST :
382db1fda10SXin LI             tws_aen_synctime_with_host(sc);
383db1fda10SXin LI             break;
384db1fda10SXin LI         case TWS_AEN_QUEUE_EMPTY :
385db1fda10SXin LI             break;
386db1fda10SXin LI         default :
387db1fda10SXin LI             bzero(&event, sizeof(struct tws_event_packet));
388db1fda10SXin LI             event.sequence_id = sc->seq_id;
389db1fda10SXin LI             event.time_stamp_sec = (u_int32_t)TWS_LOCAL_TIME;
390db1fda10SXin LI             event.aen_code = sense->status_block.error;
391db1fda10SXin LI             event.severity = sense->status_block.res__severity & 0x7;
392db1fda10SXin LI             event.event_src = TWS_SRC_CTRL_EVENT;
393db1fda10SXin LI             strcpy(event.severity_str, tws_sev_str[event.severity]);
394db1fda10SXin LI             event.retrieved = TWS_AEN_NOT_RETRIEVED;
395db1fda10SXin LI 
396db1fda10SXin LI             bcopy(sense->err_specific_desc, event.parameter_data,
397db1fda10SXin LI                                     TWS_ERROR_SPECIFIC_DESC_LEN);
398db1fda10SXin LI             event.parameter_data[TWS_ERROR_SPECIFIC_DESC_LEN - 1] = '\0';
399db1fda10SXin LI             event.parameter_len = (u_int8_t)strlen(event.parameter_data)+1;
400db1fda10SXin LI 
401db1fda10SXin LI             if ( event.parameter_len < TWS_ERROR_SPECIFIC_DESC_LEN ) {
402db1fda10SXin LI                 event.parameter_len += ((u_int8_t)strlen(event.parameter_data +
403db1fda10SXin LI                                                 event.parameter_len) + 1);
404db1fda10SXin LI             }
405db1fda10SXin LI 
406db1fda10SXin LI             device_printf(sc->tws_dev, "%s: (0x%02X: 0x%04X): %s: %s\n",
407db1fda10SXin LI                 event.severity_str,
408db1fda10SXin LI                 event.event_src,
409db1fda10SXin LI                 event.aen_code,
410db1fda10SXin LI                 event.parameter_data +
411db1fda10SXin LI                      (strlen(event.parameter_data) + 1),
412db1fda10SXin LI                 event.parameter_data);
413db1fda10SXin LI 
414db1fda10SXin LI             mtx_lock(&sc->gen_lock);
415db1fda10SXin LI             tws_circular_aenq_insert(sc, &sc->aen_q, &event);
416db1fda10SXin LI             sc->seq_id++;
417db1fda10SXin LI             mtx_unlock(&sc->gen_lock);
418db1fda10SXin LI             break;
419db1fda10SXin LI     }
420db1fda10SXin LI 
421db1fda10SXin LI     free(req->data, M_TWS);
422db1fda10SXin LI 
423db1fda10SXin LI     req->state = TWS_REQ_STATE_FREE;
424db1fda10SXin LI 
425db1fda10SXin LI     if ( aen_code != TWS_AEN_QUEUE_EMPTY ) {
426db1fda10SXin LI         /* timeout(tws_fetch_aen, sc, 1);*/
427db1fda10SXin LI         sc->stats.num_aens++;
428db1fda10SXin LI         tws_fetch_aen((void *)sc);
429db1fda10SXin LI     }
430db1fda10SXin LI }
431db1fda10SXin LI 
432db1fda10SXin LI void
tws_cmd_complete(struct tws_request * req)433db1fda10SXin LI tws_cmd_complete(struct tws_request *req)
434db1fda10SXin LI {
435db1fda10SXin LI     struct tws_softc *sc = req->sc;
436db1fda10SXin LI 
437166a4e47SJohn Baldwin     callout_stop(&req->timeout);
438db1fda10SXin LI     tws_unmap_request(sc, req);
439db1fda10SXin LI }
440db1fda10SXin LI 
441db1fda10SXin LI static void
tws_err_complete(struct tws_softc * sc,u_int64_t mfa)442db1fda10SXin LI tws_err_complete(struct tws_softc *sc, u_int64_t mfa)
443db1fda10SXin LI {
444db1fda10SXin LI     struct tws_command_header *hdr;
445db1fda10SXin LI     struct tws_sense *sen;
446db1fda10SXin LI     struct tws_request *req;
447db1fda10SXin LI     u_int16_t req_id;
448db1fda10SXin LI     u_int32_t reg, status;
449db1fda10SXin LI 
450db1fda10SXin LI     if ( !mfa ) {
451db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "null mfa", 0, mfa);
452db1fda10SXin LI         return;
453db1fda10SXin LI     } else {
454db1fda10SXin LI         /* lookup the sense */
455db1fda10SXin LI         sen = tws_find_sense_from_mfa(sc, mfa);
456db1fda10SXin LI         if ( sen == NULL ) {
457db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "found null req", 0, mfa);
458db1fda10SXin LI             return;
459db1fda10SXin LI         }
460db1fda10SXin LI         hdr = sen->hdr;
461db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "sen, hdr", sen, hdr);
462db1fda10SXin LI         req_id = hdr->header_desc.request_id;
463db1fda10SXin LI         req = &sc->reqs[req_id];
464db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "req, id", req, req_id);
465db1fda10SXin LI         if ( req->error_code != TWS_REQ_RET_SUBMIT_SUCCESS )
466db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "submit failure?", 0, req->error_code);
467db1fda10SXin LI     }
468db1fda10SXin LI 
469db1fda10SXin LI     switch (req->type) {
470db1fda10SXin LI         case TWS_REQ_TYPE_PASSTHRU :
471db1fda10SXin LI             tws_passthru_err_complete(req, hdr);
472db1fda10SXin LI             break;
473db1fda10SXin LI         case TWS_REQ_TYPE_GETSET_PARAM :
474db1fda10SXin LI             tws_getset_param_complete(req);
475db1fda10SXin LI             break;
476db1fda10SXin LI         case TWS_REQ_TYPE_SCSI_IO :
477db1fda10SXin LI             tws_scsi_err_complete(req, hdr);
478db1fda10SXin LI             break;
479db1fda10SXin LI 
480db1fda10SXin LI     }
481db1fda10SXin LI 
482db1fda10SXin LI     mtx_lock(&sc->io_lock);
483db1fda10SXin LI     hdr->header_desc.size_header = 128;
484db1fda10SXin LI     reg = (u_int32_t)( mfa>>32);
485db1fda10SXin LI     tws_write_reg(sc, TWS_I2O0_HOBQPH, reg, 4);
486db1fda10SXin LI     reg = (u_int32_t)(mfa);
487db1fda10SXin LI     tws_write_reg(sc, TWS_I2O0_HOBQPL, reg, 4);
488db1fda10SXin LI 
489db1fda10SXin LI     status = tws_read_reg(sc, TWS_I2O0_STATUS, 4);
490db1fda10SXin LI     if ( status & TWS_BIT13 ) {
491db1fda10SXin LI         device_printf(sc->tws_dev,  "OBFL Overrun\n");
492db1fda10SXin LI         sc->obfl_q_overrun = true;
493db1fda10SXin LI     }
494db1fda10SXin LI     mtx_unlock(&sc->io_lock);
495db1fda10SXin LI }
496db1fda10SXin LI 
497db1fda10SXin LI static void
tws_scsi_err_complete(struct tws_request * req,struct tws_command_header * hdr)498db1fda10SXin LI tws_scsi_err_complete(struct tws_request *req, struct tws_command_header *hdr)
499db1fda10SXin LI {
500db1fda10SXin LI     u_int8_t *sense_data;
501db1fda10SXin LI     struct tws_softc *sc = req->sc;
502db1fda10SXin LI     union ccb *ccb = req->ccb_ptr;
503db1fda10SXin LI 
504db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "sbe, cmd_status", hdr->status_block.error,
505db1fda10SXin LI                                  req->cmd_pkt->cmd.pkt_a.status);
506db1fda10SXin LI     if ( hdr->status_block.error == TWS_ERROR_LOGICAL_UNIT_NOT_SUPPORTED ||
507db1fda10SXin LI          hdr->status_block.error == TWS_ERROR_UNIT_OFFLINE ) {
508db1fda10SXin LI         if ( ccb->ccb_h.target_lun ) {
509db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "invalid lun error",0,0);
5106aa34683SJim Harris             ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
511db1fda10SXin LI         } else {
512db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "invalid target error",0,0);
5136aa34683SJim Harris             ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
514db1fda10SXin LI         }
515db1fda10SXin LI 
516db1fda10SXin LI     } else {
517db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "scsi status  error",0,0);
518db1fda10SXin LI         ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
519db1fda10SXin LI         if (((ccb->csio.cdb_io.cdb_bytes[0] == 0x1A) &&
520db1fda10SXin LI               (hdr->status_block.error == TWS_ERROR_NOT_SUPPORTED))) {
521db1fda10SXin LI             ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
522db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "page mode not supported",0,0);
523db1fda10SXin LI         }
524db1fda10SXin LI     }
525db1fda10SXin LI 
526db1fda10SXin LI     /* if there were no error simply mark complete error */
527db1fda10SXin LI     if (ccb->ccb_h.status == 0)
528db1fda10SXin LI         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
529db1fda10SXin LI 
530db1fda10SXin LI     sense_data = (u_int8_t *)&ccb->csio.sense_data;
531db1fda10SXin LI     if (sense_data) {
532db1fda10SXin LI         memcpy(sense_data, hdr->sense_data, TWS_SENSE_DATA_LENGTH );
533db1fda10SXin LI         ccb->csio.sense_len = TWS_SENSE_DATA_LENGTH;
534db1fda10SXin LI         ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
535db1fda10SXin LI     }
536db1fda10SXin LI     ccb->csio.scsi_status = req->cmd_pkt->cmd.pkt_a.status;
537db1fda10SXin LI 
538db1fda10SXin LI     ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
539db1fda10SXin LI     mtx_lock(&sc->sim_lock);
540db1fda10SXin LI     xpt_done(ccb);
541db1fda10SXin LI     mtx_unlock(&sc->sim_lock);
542db1fda10SXin LI 
543166a4e47SJohn Baldwin     callout_stop(&req->timeout);
544db1fda10SXin LI     tws_unmap_request(req->sc, req);
545db1fda10SXin LI     mtx_lock(&sc->q_lock);
546db1fda10SXin LI     tws_q_remove_request(sc, req, TWS_BUSY_Q);
547db1fda10SXin LI     tws_q_insert_tail(sc, req, TWS_FREE_Q);
548db1fda10SXin LI     mtx_unlock(&sc->q_lock);
549db1fda10SXin LI }
550db1fda10SXin LI 
551db1fda10SXin LI static void
tws_passthru_err_complete(struct tws_request * req,struct tws_command_header * hdr)552db1fda10SXin LI tws_passthru_err_complete(struct tws_request *req,
553db1fda10SXin LI                                           struct tws_command_header *hdr)
554db1fda10SXin LI {
555db1fda10SXin LI     TWS_TRACE_DEBUG(req->sc, "entry", hdr, req->request_id);
556db1fda10SXin LI     req->error_code = hdr->status_block.error;
557db1fda10SXin LI     memcpy(&(req->cmd_pkt->hdr), hdr, sizeof(struct tws_command_header));
558db1fda10SXin LI     tws_passthru_complete(req);
559db1fda10SXin LI }
560db1fda10SXin LI 
561db1fda10SXin LI static void
tws_drain_busy_queue(struct tws_softc * sc)562db1fda10SXin LI tws_drain_busy_queue(struct tws_softc *sc)
563db1fda10SXin LI {
564db1fda10SXin LI     struct tws_request *req;
565db1fda10SXin LI     union ccb          *ccb;
566db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry", 0, 0);
567db1fda10SXin LI 
568db1fda10SXin LI     mtx_lock(&sc->q_lock);
569db1fda10SXin LI     req = tws_q_remove_tail(sc, TWS_BUSY_Q);
570db1fda10SXin LI     mtx_unlock(&sc->q_lock);
571db1fda10SXin LI     while ( req ) {
572db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "moved to TWS_COMPLETE_Q", 0, req->request_id);
573166a4e47SJohn Baldwin 	callout_stop(&req->timeout);
574db1fda10SXin LI 
575db1fda10SXin LI         req->error_code = TWS_REQ_RET_RESET;
576db1fda10SXin LI         ccb = (union ccb *)(req->ccb_ptr);
577db1fda10SXin LI 
578db1fda10SXin LI         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
579db1fda10SXin LI         ccb->ccb_h.status |=  CAM_REQUEUE_REQ;
580db1fda10SXin LI         ccb->ccb_h.status |=  CAM_SCSI_BUS_RESET;
581db1fda10SXin LI 
582db1fda10SXin LI         tws_unmap_request(req->sc, req);
583db1fda10SXin LI 
584db1fda10SXin LI         mtx_lock(&sc->sim_lock);
585db1fda10SXin LI         xpt_done(req->ccb_ptr);
586db1fda10SXin LI         mtx_unlock(&sc->sim_lock);
587db1fda10SXin LI 
588db1fda10SXin LI         mtx_lock(&sc->q_lock);
589db1fda10SXin LI         tws_q_insert_tail(sc, req, TWS_FREE_Q);
590db1fda10SXin LI         req = tws_q_remove_tail(sc, TWS_BUSY_Q);
591db1fda10SXin LI         mtx_unlock(&sc->q_lock);
592db1fda10SXin LI     }
593db1fda10SXin LI }
594db1fda10SXin LI 
595db1fda10SXin LI static void
tws_drain_reserved_reqs(struct tws_softc * sc)596db1fda10SXin LI tws_drain_reserved_reqs(struct tws_softc *sc)
597db1fda10SXin LI {
598db1fda10SXin LI     struct tws_request *r;
599db1fda10SXin LI 
600db1fda10SXin LI     r = &sc->reqs[TWS_REQ_TYPE_AEN_FETCH];
601db1fda10SXin LI     if ( r->state != TWS_REQ_STATE_FREE ) {
602db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "reset aen req", 0, 0);
603166a4e47SJohn Baldwin 	callout_stop(&r->timeout);
604db1fda10SXin LI         tws_unmap_request(sc, r);
605db1fda10SXin LI         free(r->data, M_TWS);
606db1fda10SXin LI         r->state = TWS_REQ_STATE_FREE;
607db1fda10SXin LI         r->error_code = TWS_REQ_RET_RESET;
608db1fda10SXin LI     }
609db1fda10SXin LI 
610db1fda10SXin LI     r = &sc->reqs[TWS_REQ_TYPE_PASSTHRU];
611db1fda10SXin LI     if ( r->state == TWS_REQ_STATE_BUSY ) {
612db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "reset passthru req", 0, 0);
613db1fda10SXin LI         r->error_code = TWS_REQ_RET_RESET;
614db1fda10SXin LI     }
615db1fda10SXin LI 
616db1fda10SXin LI     r = &sc->reqs[TWS_REQ_TYPE_GETSET_PARAM];
617db1fda10SXin LI     if ( r->state != TWS_REQ_STATE_FREE ) {
618db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "reset setparam req", 0, 0);
619166a4e47SJohn Baldwin 	callout_stop(&r->timeout);
620db1fda10SXin LI         tws_unmap_request(sc, r);
621db1fda10SXin LI         free(r->data, M_TWS);
622db1fda10SXin LI         r->state = TWS_REQ_STATE_FREE;
623db1fda10SXin LI         r->error_code = TWS_REQ_RET_RESET;
624db1fda10SXin LI     }
625db1fda10SXin LI }
626db1fda10SXin LI 
627db1fda10SXin LI static void
tws_drain_response_queue(struct tws_softc * sc)628db1fda10SXin LI tws_drain_response_queue(struct tws_softc *sc)
629db1fda10SXin LI {
630db1fda10SXin LI     u_int16_t req_id;
631db1fda10SXin LI     u_int64_t mfa;
632db1fda10SXin LI     while ( tws_get_response(sc, &req_id, &mfa) );
633db1fda10SXin LI }
634db1fda10SXin LI 
635db1fda10SXin LI static int32_t
tws_execute_scsi(struct tws_softc * sc,union ccb * ccb)636db1fda10SXin LI tws_execute_scsi(struct tws_softc *sc, union ccb *ccb)
637db1fda10SXin LI {
638db1fda10SXin LI     struct tws_command_packet *cmd_pkt;
639db1fda10SXin LI     struct tws_request *req;
640db1fda10SXin LI     struct ccb_hdr *ccb_h = &(ccb->ccb_h);
641db1fda10SXin LI     struct ccb_scsiio *csio = &(ccb->csio);
642db1fda10SXin LI     int error;
643db1fda10SXin LI     u_int16_t lun;
644db1fda10SXin LI 
645db1fda10SXin LI     mtx_assert(&sc->sim_lock, MA_OWNED);
646db1fda10SXin LI     if (ccb_h->target_id >= TWS_MAX_NUM_UNITS) {
647db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "traget id too big", ccb_h->target_id, ccb_h->target_lun);
648db1fda10SXin LI         ccb_h->status |= CAM_TID_INVALID;
649db1fda10SXin LI         xpt_done(ccb);
650db1fda10SXin LI         return(0);
651db1fda10SXin LI     }
652db1fda10SXin LI     if (ccb_h->target_lun >= TWS_MAX_NUM_LUNS) {
653db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "target lun 2 big", ccb_h->target_id, ccb_h->target_lun);
654db1fda10SXin LI         ccb_h->status |= CAM_LUN_INVALID;
655db1fda10SXin LI         xpt_done(ccb);
656db1fda10SXin LI         return(0);
657db1fda10SXin LI     }
658db1fda10SXin LI 
659db1fda10SXin LI     if(ccb_h->flags & CAM_CDB_PHYS) {
660db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "cdb phy", ccb_h->target_id, ccb_h->target_lun);
661db1fda10SXin LI         ccb_h->status = CAM_REQ_INVALID;
662db1fda10SXin LI         xpt_done(ccb);
663db1fda10SXin LI         return(0);
664db1fda10SXin LI     }
665db1fda10SXin LI 
666db1fda10SXin LI     /*
667db1fda10SXin LI      * We are going to work on this request.  Mark it as enqueued (though
668db1fda10SXin LI      * we don't actually queue it...)
669db1fda10SXin LI      */
670db1fda10SXin LI     ccb_h->status |= CAM_SIM_QUEUED;
671db1fda10SXin LI 
672db1fda10SXin LI     req = tws_get_request(sc, TWS_REQ_TYPE_SCSI_IO);
673db1fda10SXin LI     if ( !req ) {
674db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "no reqs", ccb_h->target_id, ccb_h->target_lun);
675db1fda10SXin LI         ccb_h->status |= CAM_REQUEUE_REQ;
676db1fda10SXin LI         xpt_done(ccb);
677db1fda10SXin LI         return(0);
678db1fda10SXin LI     }
679db1fda10SXin LI 
680db1fda10SXin LI     if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
681db1fda10SXin LI         if(ccb_h->flags & CAM_DIR_IN)
682db1fda10SXin LI             req->flags |= TWS_DIR_IN;
683db1fda10SXin LI         if(ccb_h->flags & CAM_DIR_OUT)
684db1fda10SXin LI             req->flags |= TWS_DIR_OUT;
685db1fda10SXin LI     } else {
686db1fda10SXin LI         req->flags = TWS_DIR_NONE; /* no data */
687db1fda10SXin LI     }
688db1fda10SXin LI 
689db1fda10SXin LI     req->type = TWS_REQ_TYPE_SCSI_IO;
690db1fda10SXin LI     req->cb = tws_scsi_complete;
691db1fda10SXin LI 
692db1fda10SXin LI     cmd_pkt = req->cmd_pkt;
693db1fda10SXin LI     /* cmd_pkt->hdr.header_desc.size_header = 128; */
694db1fda10SXin LI     cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI;
695db1fda10SXin LI     cmd_pkt->cmd.pkt_a.unit = ccb_h->target_id;
696db1fda10SXin LI     cmd_pkt->cmd.pkt_a.status = 0;
697db1fda10SXin LI     cmd_pkt->cmd.pkt_a.sgl_offset = 16;
698db1fda10SXin LI 
699db1fda10SXin LI     /* lower nibble */
700db1fda10SXin LI     lun = ccb_h->target_lun & 0XF;
701db1fda10SXin LI     lun = lun << 12;
702db1fda10SXin LI     cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun | req->request_id;
703db1fda10SXin LI     /* upper nibble */
704db1fda10SXin LI     lun = ccb_h->target_lun & 0XF0;
705db1fda10SXin LI     lun = lun << 8;
706db1fda10SXin LI     cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries = lun;
707db1fda10SXin LI 
708db1fda10SXin LI #ifdef TWS_DEBUG
709db1fda10SXin LI     if ( csio->cdb_len > 16 )
710db1fda10SXin LI          TWS_TRACE(sc, "cdb len too big", ccb_h->target_id, csio->cdb_len);
711db1fda10SXin LI #endif
712db1fda10SXin LI 
713db1fda10SXin LI     if(ccb_h->flags & CAM_CDB_POINTER)
714db1fda10SXin LI         bcopy(csio->cdb_io.cdb_ptr, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len);
715db1fda10SXin LI     else
716db1fda10SXin LI         bcopy(csio->cdb_io.cdb_bytes, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len);
717db1fda10SXin LI 
718dd0b4fb6SKonstantin Belousov     req->data = ccb;
719dd0b4fb6SKonstantin Belousov     req->flags |= TWS_DATA_CCB;
720db1fda10SXin LI     /* save ccb ptr */
721db1fda10SXin LI     req->ccb_ptr = ccb;
722db1fda10SXin LI     /*
723db1fda10SXin LI      * tws_map_load_data_callback will fill in the SGL,
724db1fda10SXin LI      * and submit the I/O.
725db1fda10SXin LI      */
726db1fda10SXin LI     sc->stats.scsi_ios++;
72785c9dd9dSSteven Hartland     callout_reset_sbt(&req->timeout, SBT_1MS * ccb->ccb_h.timeout, 0,
72885c9dd9dSSteven Hartland       tws_timeout, req, 0);
729db1fda10SXin LI     error = tws_map_request(sc, req);
730db1fda10SXin LI     return(error);
731db1fda10SXin LI }
732db1fda10SXin LI 
733db1fda10SXin LI int
tws_send_scsi_cmd(struct tws_softc * sc,int cmd)734db1fda10SXin LI tws_send_scsi_cmd(struct tws_softc *sc, int cmd)
735db1fda10SXin LI {
736db1fda10SXin LI     struct tws_request *req;
737db1fda10SXin LI     struct tws_command_packet *cmd_pkt;
738db1fda10SXin LI     int error;
739db1fda10SXin LI 
740db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry",sc, cmd);
741db1fda10SXin LI     req = tws_get_request(sc, TWS_REQ_TYPE_AEN_FETCH);
742db1fda10SXin LI 
743db1fda10SXin LI     if ( req == NULL )
744db1fda10SXin LI         return(ENOMEM);
745db1fda10SXin LI 
746db1fda10SXin LI     req->cb = tws_aen_complete;
747db1fda10SXin LI 
748db1fda10SXin LI     cmd_pkt = req->cmd_pkt;
749db1fda10SXin LI     cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI;
750db1fda10SXin LI     cmd_pkt->cmd.pkt_a.status = 0;
751db1fda10SXin LI     cmd_pkt->cmd.pkt_a.unit = 0;
752db1fda10SXin LI     cmd_pkt->cmd.pkt_a.sgl_offset = 16;
753db1fda10SXin LI     cmd_pkt->cmd.pkt_a.lun_l4__req_id = req->request_id;
754db1fda10SXin LI 
755db1fda10SXin LI     cmd_pkt->cmd.pkt_a.cdb[0] = (u_int8_t)cmd;
756db1fda10SXin LI     cmd_pkt->cmd.pkt_a.cdb[4] = 128;
757db1fda10SXin LI 
758db1fda10SXin LI     req->length = TWS_SECTOR_SIZE;
759db1fda10SXin LI     req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT);
760db1fda10SXin LI     if ( req->data == NULL )
761db1fda10SXin LI         return(ENOMEM);
762db1fda10SXin LI     bzero(req->data, TWS_SECTOR_SIZE);
763db1fda10SXin LI     req->flags = TWS_DIR_IN;
764db1fda10SXin LI 
765166a4e47SJohn Baldwin     callout_reset(&req->timeout, (TWS_IO_TIMEOUT * hz), tws_timeout, req);
766db1fda10SXin LI     error = tws_map_request(sc, req);
767db1fda10SXin LI     return(error);
768db1fda10SXin LI 
769db1fda10SXin LI }
770db1fda10SXin LI 
771db1fda10SXin LI int
tws_set_param(struct tws_softc * sc,u_int32_t table_id,u_int32_t param_id,u_int32_t param_size,void * data)772db1fda10SXin LI tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id,
773db1fda10SXin LI               u_int32_t param_size, void *data)
774db1fda10SXin LI {
775db1fda10SXin LI     struct tws_request *req;
776db1fda10SXin LI     struct tws_command_packet *cmd_pkt;
777db1fda10SXin LI     union tws_command_giga *cmd;
778db1fda10SXin LI     struct tws_getset_param *param;
779db1fda10SXin LI     int error;
780db1fda10SXin LI 
781db1fda10SXin LI     req = tws_get_request(sc, TWS_REQ_TYPE_GETSET_PARAM);
782db1fda10SXin LI     if ( req == NULL ) {
783db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "null req", 0, 0);
784db1fda10SXin LI         return(ENOMEM);
785db1fda10SXin LI     }
786db1fda10SXin LI 
787db1fda10SXin LI     req->length = TWS_SECTOR_SIZE;
788db1fda10SXin LI     req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT);
789db1fda10SXin LI     if ( req->data == NULL )
790db1fda10SXin LI         return(ENOMEM);
791db1fda10SXin LI     bzero(req->data, TWS_SECTOR_SIZE);
792db1fda10SXin LI     param = (struct tws_getset_param *)req->data;
793db1fda10SXin LI 
794db1fda10SXin LI     req->cb = tws_getset_param_complete;
795db1fda10SXin LI     req->flags = TWS_DIR_OUT;
796db1fda10SXin LI     cmd_pkt = req->cmd_pkt;
797db1fda10SXin LI 
798db1fda10SXin LI     cmd = &cmd_pkt->cmd.pkt_g;
799db1fda10SXin LI     cmd->param.sgl_off__opcode =
800db1fda10SXin LI             BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_SET_PARAM);
801db1fda10SXin LI     cmd->param.request_id = (u_int8_t)req->request_id;
802db1fda10SXin LI     cmd->param.host_id__unit = 0;
803db1fda10SXin LI     cmd->param.param_count = 1;
804db1fda10SXin LI     cmd->param.size = 2; /* map routine will add sgls */
805db1fda10SXin LI 
806db1fda10SXin LI     /* Specify which parameter we want to set. */
807db1fda10SXin LI     param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR);
808db1fda10SXin LI     param->parameter_id = (u_int8_t)(param_id);
809db1fda10SXin LI     param->parameter_size_bytes = (u_int16_t)param_size;
810db1fda10SXin LI     memcpy(param->data, data, param_size);
811db1fda10SXin LI 
812166a4e47SJohn Baldwin     callout_reset(&req->timeout, (TWS_IOCTL_TIMEOUT * hz), tws_timeout, req);
813db1fda10SXin LI     error = tws_map_request(sc, req);
814db1fda10SXin LI     return(error);
815db1fda10SXin LI 
816db1fda10SXin LI }
817db1fda10SXin LI 
818db1fda10SXin LI int
tws_get_param(struct tws_softc * sc,u_int32_t table_id,u_int32_t param_id,u_int32_t param_size,void * data)819db1fda10SXin LI tws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id,
820db1fda10SXin LI               u_int32_t param_size, void *data)
821db1fda10SXin LI {
822db1fda10SXin LI     struct tws_request *req;
823db1fda10SXin LI     struct tws_command_packet *cmd_pkt;
824db1fda10SXin LI     union tws_command_giga *cmd;
825db1fda10SXin LI     struct tws_getset_param *param;
826db1fda10SXin LI     u_int16_t reqid;
827db1fda10SXin LI     u_int64_t mfa;
828db1fda10SXin LI     int error = SUCCESS;
829db1fda10SXin LI 
830db1fda10SXin LI     req = tws_get_request(sc, TWS_REQ_TYPE_GETSET_PARAM);
831db1fda10SXin LI     if ( req == NULL ) {
832db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "null req", 0, 0);
833db1fda10SXin LI         return(FAILURE);
834db1fda10SXin LI     }
835db1fda10SXin LI 
836db1fda10SXin LI     req->length = TWS_SECTOR_SIZE;
837db1fda10SXin LI     req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT);
838db1fda10SXin LI     if ( req->data == NULL )
839db1fda10SXin LI         return(FAILURE);
840db1fda10SXin LI     bzero(req->data, TWS_SECTOR_SIZE);
841db1fda10SXin LI     param = (struct tws_getset_param *)req->data;
842db1fda10SXin LI 
843db1fda10SXin LI     req->cb = NULL;
844db1fda10SXin LI     req->flags = TWS_DIR_IN;
845db1fda10SXin LI     cmd_pkt = req->cmd_pkt;
846db1fda10SXin LI 
847db1fda10SXin LI     cmd = &cmd_pkt->cmd.pkt_g;
848db1fda10SXin LI     cmd->param.sgl_off__opcode =
849db1fda10SXin LI             BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_GET_PARAM);
850db1fda10SXin LI     cmd->param.request_id = (u_int8_t)req->request_id;
851db1fda10SXin LI     cmd->param.host_id__unit = 0;
852db1fda10SXin LI     cmd->param.param_count = 1;
853db1fda10SXin LI     cmd->param.size = 2; /* map routine will add sgls */
854db1fda10SXin LI 
855db1fda10SXin LI     /* Specify which parameter we want to set. */
856db1fda10SXin LI     param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR);
857db1fda10SXin LI     param->parameter_id = (u_int8_t)(param_id);
858db1fda10SXin LI     param->parameter_size_bytes = (u_int16_t)param_size;
859db1fda10SXin LI 
860db1fda10SXin LI     error = tws_map_request(sc, req);
861db1fda10SXin LI     if (!error) {
862db1fda10SXin LI         reqid = tws_poll4_response(sc, &mfa);
863db1fda10SXin LI         tws_unmap_request(sc, req);
864db1fda10SXin LI 
865db1fda10SXin LI         if ( reqid == TWS_REQ_TYPE_GETSET_PARAM ) {
866db1fda10SXin LI             memcpy(data, param->data, param_size);
867db1fda10SXin LI         } else {
868db1fda10SXin LI             error = FAILURE;
869db1fda10SXin LI         }
870db1fda10SXin LI     }
871db1fda10SXin LI 
872db1fda10SXin LI     free(req->data, M_TWS);
873db1fda10SXin LI     req->state = TWS_REQ_STATE_FREE;
874db1fda10SXin LI     return(error);
875db1fda10SXin LI 
876db1fda10SXin LI }
877db1fda10SXin LI 
878db1fda10SXin LI void
tws_unmap_request(struct tws_softc * sc,struct tws_request * req)879db1fda10SXin LI tws_unmap_request(struct tws_softc *sc, struct tws_request *req)
880db1fda10SXin LI {
881db1fda10SXin LI     if (req->data != NULL) {
882db1fda10SXin LI         if ( req->flags & TWS_DIR_IN )
883db1fda10SXin LI             bus_dmamap_sync(sc->data_tag, req->dma_map,
884db1fda10SXin LI                                             BUS_DMASYNC_POSTREAD);
885db1fda10SXin LI         if ( req->flags & TWS_DIR_OUT )
886db1fda10SXin LI             bus_dmamap_sync(sc->data_tag, req->dma_map,
887db1fda10SXin LI                                             BUS_DMASYNC_POSTWRITE);
888db1fda10SXin LI         mtx_lock(&sc->io_lock);
889db1fda10SXin LI         bus_dmamap_unload(sc->data_tag, req->dma_map);
890db1fda10SXin LI         mtx_unlock(&sc->io_lock);
891db1fda10SXin LI     }
892db1fda10SXin LI }
893db1fda10SXin LI 
894db1fda10SXin LI int32_t
tws_map_request(struct tws_softc * sc,struct tws_request * req)895db1fda10SXin LI tws_map_request(struct tws_softc *sc, struct tws_request *req)
896db1fda10SXin LI {
897db1fda10SXin LI     int32_t error = 0;
898db1fda10SXin LI 
899db1fda10SXin LI     /* If the command involves data, map that too. */
900db1fda10SXin LI     if (req->data != NULL) {
901db1fda10SXin LI         int my_flags = ((req->type == TWS_REQ_TYPE_SCSI_IO) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT);
902db1fda10SXin LI 
903db1fda10SXin LI         /*
904db1fda10SXin LI          * Map the data buffer into bus space and build the SG list.
905db1fda10SXin LI          */
906db1fda10SXin LI         mtx_lock(&sc->io_lock);
907dd0b4fb6SKonstantin Belousov 	if (req->flags & TWS_DATA_CCB)
908dd0b4fb6SKonstantin Belousov 		error = bus_dmamap_load_ccb(sc->data_tag, req->dma_map,
909dd0b4fb6SKonstantin Belousov 					    req->data,
910dd0b4fb6SKonstantin Belousov 					    tws_dmamap_data_load_cbfn, req,
911dd0b4fb6SKonstantin Belousov 					    my_flags);
912dd0b4fb6SKonstantin Belousov 	else
913db1fda10SXin LI 		error = bus_dmamap_load(sc->data_tag, req->dma_map,
914db1fda10SXin LI 					req->data, req->length,
915db1fda10SXin LI 					tws_dmamap_data_load_cbfn, req,
916db1fda10SXin LI 					my_flags);
917db1fda10SXin LI         mtx_unlock(&sc->io_lock);
918db1fda10SXin LI 
919db1fda10SXin LI         if (error == EINPROGRESS) {
920db1fda10SXin LI             TWS_TRACE(sc, "in progress", 0, error);
921db1fda10SXin LI             tws_freeze_simq(sc, req);
922c5f33959SXin LI             error = 0;  // EINPROGRESS is not a fatal error.
923db1fda10SXin LI         }
924db1fda10SXin LI     } else { /* no data involved */
925db1fda10SXin LI         error = tws_submit_command(sc, req);
926db1fda10SXin LI     }
927db1fda10SXin LI     return(error);
928db1fda10SXin LI }
929db1fda10SXin LI 
930db1fda10SXin LI static void
tws_dmamap_data_load_cbfn(void * arg,bus_dma_segment_t * segs,int nseg,int error)931db1fda10SXin LI tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
932db1fda10SXin LI                             int nseg, int error)
933db1fda10SXin LI {
934db1fda10SXin LI     struct tws_request *req = (struct tws_request *)arg;
935db1fda10SXin LI     struct tws_softc *sc = req->sc;
936db1fda10SXin LI     u_int16_t sgls = nseg;
937db1fda10SXin LI     void *sgl_ptr;
938db1fda10SXin LI     struct tws_cmd_generic *gcmd;
939db1fda10SXin LI 
940c5f33959SXin LI     if ( error ) {
941c5f33959SXin LI         TWS_TRACE(sc, "SOMETHING BAD HAPPENED! error = %d\n", error, 0);
942c5f33959SXin LI     }
943c5f33959SXin LI 
944db1fda10SXin LI     if ( error == EFBIG ) {
945db1fda10SXin LI         TWS_TRACE(sc, "not enough data segs", 0, nseg);
946db1fda10SXin LI         req->error_code = error;
947db1fda10SXin LI         req->ccb_ptr->ccb_h.status = CAM_REQ_TOO_BIG;
948db1fda10SXin LI         return;
949db1fda10SXin LI     }
950db1fda10SXin LI 
951db1fda10SXin LI     if ( req->flags & TWS_DIR_IN )
952db1fda10SXin LI         bus_dmamap_sync(req->sc->data_tag, req->dma_map,
953db1fda10SXin LI                                             BUS_DMASYNC_PREREAD);
954db1fda10SXin LI     if ( req->flags & TWS_DIR_OUT )
955db1fda10SXin LI         bus_dmamap_sync(req->sc->data_tag, req->dma_map,
956db1fda10SXin LI                                         BUS_DMASYNC_PREWRITE);
957db1fda10SXin LI     if ( segs ) {
958db1fda10SXin LI         if ( (req->type == TWS_REQ_TYPE_PASSTHRU &&
959db1fda10SXin LI              GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) !=
960db1fda10SXin LI                             TWS_FW_CMD_EXECUTE_SCSI) ||
961db1fda10SXin LI               req->type == TWS_REQ_TYPE_GETSET_PARAM) {
962db1fda10SXin LI             gcmd = &req->cmd_pkt->cmd.pkt_g.generic;
963db1fda10SXin LI             sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size;
964db1fda10SXin LI             gcmd->size += sgls *
965db1fda10SXin LI                           ((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 : 2 );
966db1fda10SXin LI             tws_fill_sg_list(req->sc, (void *)segs, sgl_ptr, sgls);
967db1fda10SXin LI 
968db1fda10SXin LI         } else {
969db1fda10SXin LI             tws_fill_sg_list(req->sc, (void *)segs,
970c5f33959SXin LI                       (void *)&(req->cmd_pkt->cmd.pkt_a.sg_list), sgls);
971db1fda10SXin LI             req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ;
972db1fda10SXin LI         }
973db1fda10SXin LI     }
974db1fda10SXin LI 
975db1fda10SXin LI     req->error_code = tws_submit_command(req->sc, req);
976db1fda10SXin LI 
977db1fda10SXin LI }
978db1fda10SXin LI 
979db1fda10SXin LI static void
tws_fill_sg_list(struct tws_softc * sc,void * sgl_src,void * sgl_dest,u_int16_t num_sgl_entries)980db1fda10SXin LI tws_fill_sg_list(struct tws_softc *sc, void *sgl_src, void *sgl_dest,
981db1fda10SXin LI                           u_int16_t num_sgl_entries)
982db1fda10SXin LI {
983db1fda10SXin LI     int i;
984db1fda10SXin LI 
985db1fda10SXin LI     if ( sc->is64bit ) {
986db1fda10SXin LI         struct tws_sg_desc64 *sgl_s = (struct tws_sg_desc64 *)sgl_src;
987db1fda10SXin LI 
988db1fda10SXin LI         if ( !tws_use_32bit_sgls ) {
989db1fda10SXin LI             struct tws_sg_desc64 *sgl_d = (struct tws_sg_desc64 *)sgl_dest;
990db1fda10SXin LI             if ( num_sgl_entries > TWS_MAX_64BIT_SG_ELEMENTS )
991db1fda10SXin LI                 TWS_TRACE(sc, "64bit sg overflow", num_sgl_entries, 0);
992db1fda10SXin LI             for (i = 0; i < num_sgl_entries; i++) {
993db1fda10SXin LI                 sgl_d[i].address = sgl_s->address;
994db1fda10SXin LI                 sgl_d[i].length = sgl_s->length;
995db1fda10SXin LI                 sgl_d[i].flag = 0;
996db1fda10SXin LI                 sgl_d[i].reserved = 0;
997db1fda10SXin LI                 sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) +
998db1fda10SXin LI                                                sizeof(bus_dma_segment_t));
999db1fda10SXin LI             }
1000db1fda10SXin LI         } else {
1001db1fda10SXin LI             struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest;
1002db1fda10SXin LI             if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS )
1003db1fda10SXin LI                 TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0);
1004db1fda10SXin LI             for (i = 0; i < num_sgl_entries; i++) {
1005db1fda10SXin LI                 sgl_d[i].address = sgl_s->address;
1006db1fda10SXin LI                 sgl_d[i].length = sgl_s->length;
1007db1fda10SXin LI                 sgl_d[i].flag = 0;
1008db1fda10SXin LI                 sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) +
1009db1fda10SXin LI                                                sizeof(bus_dma_segment_t));
1010db1fda10SXin LI             }
1011db1fda10SXin LI         }
1012db1fda10SXin LI     } else {
1013db1fda10SXin LI         struct tws_sg_desc32 *sgl_s = (struct tws_sg_desc32 *)sgl_src;
1014db1fda10SXin LI         struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest;
1015db1fda10SXin LI 
1016db1fda10SXin LI         if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS )
1017db1fda10SXin LI             TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0);
1018db1fda10SXin LI 
1019db1fda10SXin LI         for (i = 0; i < num_sgl_entries; i++) {
1020db1fda10SXin LI             sgl_d[i].address = sgl_s[i].address;
1021db1fda10SXin LI             sgl_d[i].length = sgl_s[i].length;
1022db1fda10SXin LI             sgl_d[i].flag = 0;
1023db1fda10SXin LI         }
1024db1fda10SXin LI     }
1025db1fda10SXin LI }
1026db1fda10SXin LI 
1027db1fda10SXin LI void
tws_intr(void * arg)1028db1fda10SXin LI tws_intr(void *arg)
1029db1fda10SXin LI {
1030db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)arg;
1031db1fda10SXin LI     u_int32_t histat=0, db=0;
1032db1fda10SXin LI 
1033db1fda10SXin LI     if (!(sc)) {
1034db1fda10SXin LI         device_printf(sc->tws_dev, "null softc!!!\n");
1035db1fda10SXin LI         return;
1036db1fda10SXin LI     }
1037db1fda10SXin LI 
1038db1fda10SXin LI     if ( tws_get_state(sc) == TWS_RESET ) {
1039db1fda10SXin LI         return;
1040db1fda10SXin LI     }
1041db1fda10SXin LI 
1042db1fda10SXin LI     if ( tws_get_state(sc) != TWS_ONLINE ) {
1043db1fda10SXin LI         return;
1044db1fda10SXin LI     }
1045db1fda10SXin LI 
1046db1fda10SXin LI     sc->stats.num_intrs++;
1047db1fda10SXin LI     histat = tws_read_reg(sc, TWS_I2O0_HISTAT, 4);
1048db1fda10SXin LI     if ( histat & TWS_BIT2 ) {
1049db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "door bell :)", histat, TWS_I2O0_HISTAT);
1050db1fda10SXin LI         db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4);
1051db1fda10SXin LI         if ( db & TWS_BIT21 ) {
1052db1fda10SXin LI             tws_intr_attn_error(sc);
1053db1fda10SXin LI             return;
1054db1fda10SXin LI         }
1055db1fda10SXin LI         if ( db & TWS_BIT18 ) {
1056db1fda10SXin LI             tws_intr_attn_aen(sc);
1057db1fda10SXin LI         }
1058db1fda10SXin LI     }
1059db1fda10SXin LI 
1060db1fda10SXin LI     if ( histat & TWS_BIT3 ) {
1061db1fda10SXin LI         tws_intr_resp(sc);
1062db1fda10SXin LI     }
1063db1fda10SXin LI }
1064db1fda10SXin LI 
1065db1fda10SXin LI static void
tws_intr_attn_aen(struct tws_softc * sc)1066db1fda10SXin LI tws_intr_attn_aen(struct tws_softc *sc)
1067db1fda10SXin LI {
1068db1fda10SXin LI 
1069453130d9SPedro F. Giffuni     /* maskoff db intrs until all the aens are fetched */
1070db1fda10SXin LI     /* tws_disable_db_intr(sc); */
1071db1fda10SXin LI     tws_fetch_aen((void *)sc);
1072db1fda10SXin LI     tws_write_reg(sc, TWS_I2O0_HOBDBC, TWS_BIT18, 4);
1073a21f086aSScott Long     (void)tws_read_reg(sc, TWS_I2O0_IOBDB, 4);
1074db1fda10SXin LI 
1075db1fda10SXin LI }
1076db1fda10SXin LI 
1077db1fda10SXin LI static void
tws_intr_attn_error(struct tws_softc * sc)1078db1fda10SXin LI tws_intr_attn_error(struct tws_softc *sc)
1079db1fda10SXin LI {
1080db1fda10SXin LI 
1081db1fda10SXin LI     TWS_TRACE(sc, "attn error", 0, 0);
1082db1fda10SXin LI     tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4);
1083a21f086aSScott Long     (void)tws_read_reg(sc, TWS_I2O0_IOBDB, 4);
1084db1fda10SXin LI     device_printf(sc->tws_dev, "Micro controller error.\n");
1085db1fda10SXin LI     tws_reset(sc);
1086db1fda10SXin LI }
1087db1fda10SXin LI 
1088db1fda10SXin LI static void
tws_intr_resp(struct tws_softc * sc)1089db1fda10SXin LI tws_intr_resp(struct tws_softc *sc)
1090db1fda10SXin LI {
1091db1fda10SXin LI     u_int16_t req_id;
1092db1fda10SXin LI     u_int64_t mfa;
1093db1fda10SXin LI 
1094db1fda10SXin LI     while ( tws_get_response(sc, &req_id, &mfa) ) {
1095db1fda10SXin LI         sc->stats.reqs_out++;
1096db1fda10SXin LI         if ( req_id == TWS_INVALID_REQID ) {
1097db1fda10SXin LI             TWS_TRACE_DEBUG(sc, "invalid req_id", mfa, req_id);
1098db1fda10SXin LI             sc->stats.reqs_errored++;
1099db1fda10SXin LI             tws_err_complete(sc, mfa);
1100db1fda10SXin LI             continue;
1101db1fda10SXin LI         }
1102db1fda10SXin LI         sc->reqs[req_id].cb(&sc->reqs[req_id]);
1103db1fda10SXin LI     }
1104db1fda10SXin LI 
1105db1fda10SXin LI }
1106db1fda10SXin LI 
1107db1fda10SXin LI static void
tws_poll(struct cam_sim * sim)1108db1fda10SXin LI tws_poll(struct cam_sim *sim)
1109db1fda10SXin LI {
1110db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim);
1111db1fda10SXin LI     TWS_TRACE_DEBUG(sc, "entry", 0, 0);
1112db1fda10SXin LI     tws_intr((void *) sc);
1113db1fda10SXin LI }
1114db1fda10SXin LI 
1115db1fda10SXin LI void
tws_timeout(void * arg)1116db1fda10SXin LI tws_timeout(void *arg)
1117db1fda10SXin LI {
1118db1fda10SXin LI     struct tws_request *req = (struct tws_request *)arg;
1119db1fda10SXin LI     struct tws_softc *sc = req->sc;
1120db1fda10SXin LI 
1121db1fda10SXin LI     if ( req->error_code == TWS_REQ_RET_RESET ) {
1122db1fda10SXin LI         return;
1123db1fda10SXin LI     }
1124db1fda10SXin LI 
1125db1fda10SXin LI     mtx_lock(&sc->gen_lock);
1126db1fda10SXin LI     if ( req->error_code == TWS_REQ_RET_RESET ) {
1127db1fda10SXin LI         mtx_unlock(&sc->gen_lock);
1128db1fda10SXin LI         return;
1129db1fda10SXin LI     }
1130db1fda10SXin LI 
1131db1fda10SXin LI     if ( tws_get_state(sc) == TWS_RESET ) {
1132db1fda10SXin LI         mtx_unlock(&sc->gen_lock);
1133db1fda10SXin LI         return;
1134db1fda10SXin LI     }
1135db1fda10SXin LI 
1136db1fda10SXin LI     xpt_freeze_simq(sc->sim, 1);
1137db1fda10SXin LI 
1138db1fda10SXin LI     tws_send_event(sc, TWS_RESET_START);
1139db1fda10SXin LI 
1140db1fda10SXin LI     if (req->type == TWS_REQ_TYPE_SCSI_IO) {
1141db1fda10SXin LI         device_printf(sc->tws_dev, "I/O Request timed out... Resetting controller\n");
1142db1fda10SXin LI     } else if (req->type == TWS_REQ_TYPE_PASSTHRU) {
1143db1fda10SXin LI         device_printf(sc->tws_dev, "IOCTL Request timed out... Resetting controller\n");
1144db1fda10SXin LI     } else {
1145db1fda10SXin LI         device_printf(sc->tws_dev, "Internal Request timed out... Resetting controller\n");
1146db1fda10SXin LI     }
1147db1fda10SXin LI 
1148db1fda10SXin LI     tws_assert_soft_reset(sc);
1149db1fda10SXin LI     tws_turn_off_interrupts(sc);
1150db1fda10SXin LI     tws_reset_cb( (void*) sc );
1151db1fda10SXin LI     tws_reinit( (void*) sc );
1152db1fda10SXin LI 
1153db1fda10SXin LI //  device_printf(sc->tws_dev,  "Controller Reset complete!\n");
1154db1fda10SXin LI     tws_send_event(sc, TWS_RESET_COMPLETE);
1155db1fda10SXin LI     mtx_unlock(&sc->gen_lock);
1156db1fda10SXin LI 
1157db1fda10SXin LI     xpt_release_simq(sc->sim, 1);
1158db1fda10SXin LI }
1159db1fda10SXin LI 
1160db1fda10SXin LI void
tws_reset(void * arg)1161db1fda10SXin LI tws_reset(void *arg)
1162db1fda10SXin LI {
1163db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)arg;
1164db1fda10SXin LI 
1165db1fda10SXin LI     mtx_lock(&sc->gen_lock);
1166db1fda10SXin LI     if ( tws_get_state(sc) == TWS_RESET ) {
1167db1fda10SXin LI         mtx_unlock(&sc->gen_lock);
1168db1fda10SXin LI         return;
1169db1fda10SXin LI     }
1170db1fda10SXin LI 
1171db1fda10SXin LI     xpt_freeze_simq(sc->sim, 1);
1172db1fda10SXin LI 
1173db1fda10SXin LI     tws_send_event(sc, TWS_RESET_START);
1174db1fda10SXin LI 
1175db1fda10SXin LI     device_printf(sc->tws_dev,  "Resetting controller\n");
1176db1fda10SXin LI 
1177db1fda10SXin LI     tws_assert_soft_reset(sc);
1178db1fda10SXin LI     tws_turn_off_interrupts(sc);
1179db1fda10SXin LI     tws_reset_cb( (void*) sc );
1180db1fda10SXin LI     tws_reinit( (void*) sc );
1181db1fda10SXin LI 
1182db1fda10SXin LI //  device_printf(sc->tws_dev,  "Controller Reset complete!\n");
1183db1fda10SXin LI     tws_send_event(sc, TWS_RESET_COMPLETE);
1184db1fda10SXin LI     mtx_unlock(&sc->gen_lock);
1185db1fda10SXin LI 
1186db1fda10SXin LI     xpt_release_simq(sc->sim, 1);
1187db1fda10SXin LI }
1188db1fda10SXin LI 
1189db1fda10SXin LI static void
tws_reset_cb(void * arg)1190db1fda10SXin LI tws_reset_cb(void *arg)
1191db1fda10SXin LI {
1192db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)arg;
1193db1fda10SXin LI     time_t endt;
1194db1fda10SXin LI     int found = 0;
1195db1fda10SXin LI     u_int32_t reg;
1196db1fda10SXin LI 
1197db1fda10SXin LI     if ( tws_get_state(sc) != TWS_RESET ) {
1198db1fda10SXin LI         return;
1199db1fda10SXin LI     }
1200db1fda10SXin LI 
1201db1fda10SXin LI //  device_printf(sc->tws_dev,  "Draining Busy Queue\n");
1202db1fda10SXin LI     tws_drain_busy_queue(sc);
1203db1fda10SXin LI //  device_printf(sc->tws_dev,  "Draining Reserved Reqs\n");
1204db1fda10SXin LI     tws_drain_reserved_reqs(sc);
1205db1fda10SXin LI //  device_printf(sc->tws_dev,  "Draining Response Queue\n");
1206db1fda10SXin LI     tws_drain_response_queue(sc);
1207db1fda10SXin LI 
1208db1fda10SXin LI //  device_printf(sc->tws_dev,  "Looking for controller ready flag...\n");
1209db1fda10SXin LI     endt = TWS_LOCAL_TIME + TWS_POLL_TIMEOUT;
1210db1fda10SXin LI     while ((TWS_LOCAL_TIME <= endt) && (!found)) {
1211db1fda10SXin LI         reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4);
1212db1fda10SXin LI         if ( reg & TWS_BIT13 ) {
1213db1fda10SXin LI             found = 1;
1214db1fda10SXin LI //          device_printf(sc->tws_dev,  " ... Got it!\n");
1215db1fda10SXin LI         }
1216db1fda10SXin LI     }
1217db1fda10SXin LI     if ( !found )
1218db1fda10SXin LI             device_printf(sc->tws_dev,  " ... Controller ready flag NOT found!\n");
1219db1fda10SXin LI }
1220db1fda10SXin LI 
1221db1fda10SXin LI static void
tws_reinit(void * arg)1222db1fda10SXin LI tws_reinit(void *arg)
1223db1fda10SXin LI {
1224db1fda10SXin LI     struct tws_softc *sc = (struct tws_softc *)arg;
1225db1fda10SXin LI     int timeout_val=0;
1226db1fda10SXin LI     int try=2;
1227db1fda10SXin LI     int done=0;
1228db1fda10SXin LI 
1229db1fda10SXin LI //  device_printf(sc->tws_dev,  "Waiting for Controller Ready\n");
1230db1fda10SXin LI     while ( !done && try ) {
1231db1fda10SXin LI         if ( tws_ctlr_ready(sc) ) {
1232db1fda10SXin LI             done = 1;
1233db1fda10SXin LI             break;
1234db1fda10SXin LI         } else {
1235db1fda10SXin LI             timeout_val += 5;
1236db1fda10SXin LI             if ( timeout_val >= TWS_RESET_TIMEOUT ) {
1237db1fda10SXin LI                timeout_val = 0;
1238db1fda10SXin LI                if ( try )
1239db1fda10SXin LI                    tws_assert_soft_reset(sc);
1240db1fda10SXin LI                try--;
1241db1fda10SXin LI             }
1242db1fda10SXin LI             mtx_sleep(sc, &sc->gen_lock, 0, "tws_reinit", 5*hz);
1243db1fda10SXin LI         }
1244db1fda10SXin LI     }
1245db1fda10SXin LI 
1246db1fda10SXin LI     if (!done) {
1247db1fda10SXin LI         device_printf(sc->tws_dev,  "FAILED to get Controller Ready!\n");
1248db1fda10SXin LI         return;
1249db1fda10SXin LI     }
1250db1fda10SXin LI 
1251db1fda10SXin LI     sc->obfl_q_overrun = false;
1252db1fda10SXin LI //  device_printf(sc->tws_dev,  "Sending initConnect\n");
1253db1fda10SXin LI     if ( tws_init_connect(sc, tws_queue_depth) ) {
1254db1fda10SXin LI         TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit);
1255db1fda10SXin LI     }
1256db1fda10SXin LI     tws_init_obfl_q(sc);
1257db1fda10SXin LI 
1258db1fda10SXin LI     tws_turn_on_interrupts(sc);
1259db1fda10SXin LI 
1260def7eaf1SXin LI     wakeup_one(sc);
1261db1fda10SXin LI }
1262db1fda10SXin LI 
1263db1fda10SXin LI static void
tws_freeze_simq(struct tws_softc * sc,struct tws_request * req)1264db1fda10SXin LI tws_freeze_simq(struct tws_softc *sc, struct tws_request *req)
1265db1fda10SXin LI {
1266db1fda10SXin LI     /* Only for IO commands */
1267db1fda10SXin LI     if (req->type == TWS_REQ_TYPE_SCSI_IO) {
1268db1fda10SXin LI         union ccb   *ccb = (union ccb *)(req->ccb_ptr);
1269db1fda10SXin LI 
1270db1fda10SXin LI         xpt_freeze_simq(sc->sim, 1);
1271db1fda10SXin LI         ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1272db1fda10SXin LI         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1273db1fda10SXin LI     }
1274db1fda10SXin LI }
1275db1fda10SXin LI 
1276db1fda10SXin LI TUNABLE_INT("hw.tws.cam_depth", &tws_cam_depth);
1277