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