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