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
46static int tws_cam_depth=(TWS_MAX_REQS - TWS_RESERVED_REQS);
47static char tws_sev_str[5][8]={"","ERROR","WARNING","INFO","DEBUG"};
48
49static void  tws_action(struct cam_sim *sim, union ccb *ccb);
50static void  tws_poll(struct cam_sim *sim);
51static void tws_scsi_complete(struct tws_request *req);
52
53void tws_unmap_request(struct tws_softc *sc, struct tws_request *req);
54int32_t tws_map_request(struct tws_softc *sc, struct tws_request *req);
55int tws_bus_scan(struct tws_softc *sc);
56int tws_cam_attach(struct tws_softc *sc);
57void tws_cam_detach(struct tws_softc *sc);
58void tws_reset(void *arg);
59
60static void tws_reset_cb(void *arg);
61static void tws_reinit(void *arg);
62static int32_t tws_execute_scsi(struct tws_softc *sc, union ccb *ccb);
63static void tws_freeze_simq(struct tws_softc *sc, struct tws_request *req);
64static void tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs,
65                            int nseg, int error);
66static void tws_fill_sg_list(struct tws_softc *sc, void *sgl_src,
67                            void *sgl_dest, u_int16_t num_sgl_entries);
68static void tws_err_complete(struct tws_softc *sc, u_int64_t mfa);
69static void tws_scsi_err_complete(struct tws_request *req,
70                                               struct tws_command_header *hdr);
71static void tws_passthru_err_complete(struct tws_request *req,
72                                               struct tws_command_header *hdr);
73
74void tws_timeout(void *arg);
75static void tws_intr_attn_aen(struct tws_softc *sc);
76static void tws_intr_attn_error(struct tws_softc *sc);
77static void tws_intr_resp(struct tws_softc *sc);
78void tws_intr(void *arg);
79void tws_cmd_complete(struct tws_request *req);
80void tws_aen_complete(struct tws_request *req);
81int tws_send_scsi_cmd(struct tws_softc *sc, int cmd);
82void tws_getset_param_complete(struct tws_request *req);
83int 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);
85int 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
88extern struct tws_request *tws_get_request(struct tws_softc *sc,
89                                            u_int16_t type);
90extern void *tws_release_request(struct tws_request *req);
91extern int tws_submit_command(struct tws_softc *sc, struct tws_request *req);
92extern boolean tws_get_response(struct tws_softc *sc,
93                                           u_int16_t *req_id, u_int64_t *mfa);
94extern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req,
95                                u_int8_t q_type );
96extern struct tws_request * tws_q_remove_request(struct tws_softc *sc,
97                                   struct tws_request *req, u_int8_t q_type );
98extern void tws_send_event(struct tws_softc *sc, u_int8_t event);
99
100extern struct tws_sense *
101tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa);
102
103extern void tws_fetch_aen(void *arg);
104extern void tws_disable_db_intr(struct tws_softc *sc);
105extern void tws_enable_db_intr(struct tws_softc *sc);
106extern void tws_passthru_complete(struct tws_request *req);
107extern void tws_aen_synctime_with_host(struct tws_softc *sc);
108extern void tws_circular_aenq_insert(struct tws_softc *sc,
109                    struct tws_circular_q *cq, struct tws_event_packet *aen);
110extern int tws_use_32bit_sgls;
111extern boolean tws_ctlr_reset(struct tws_softc *sc);
112extern struct tws_request * tws_q_remove_tail(struct tws_softc *sc,
113                                                           u_int8_t q_type );
114extern void tws_turn_off_interrupts(struct tws_softc *sc);
115extern void tws_turn_on_interrupts(struct tws_softc *sc);
116extern int tws_init_connect(struct tws_softc *sc, u_int16_t mc);
117extern void tws_init_obfl_q(struct tws_softc *sc);
118extern uint8_t tws_get_state(struct tws_softc *sc);
119extern void tws_assert_soft_reset(struct tws_softc *sc);
120extern boolean tws_ctlr_ready(struct tws_softc *sc);
121extern u_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa);
122extern int tws_setup_intr(struct tws_softc *sc, int irqs);
123extern int tws_teardown_intr(struct tws_softc *sc);
124
125int
126tws_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
190void
191tws_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
204int
205tws_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
225static void
226tws_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
319static void
320tws_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
341void
342tws_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
356void
357tws_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
434void
435tws_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
443static void
444tws_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
499static void
500tws_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
553static void
554tws_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
563static void
564tws_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
597static void
598tws_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
629static void
630tws_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
637static int32_t
638tws_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
735int
736tws_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
773int
774tws_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
820int
821tws_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
880void
881tws_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
896int32_t
897tws_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
932static void
933tws_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
981static void
982tws_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
1029void
1030tws_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
1067static void
1068tws_intr_attn_aen(struct tws_softc *sc)
1069{
1070    u_int32_t db=0;
1071
1072    /* maskoff db intrs until all the aens are fetched */
1073    /* tws_disable_db_intr(sc); */
1074    tws_fetch_aen((void *)sc);
1075    tws_write_reg(sc, TWS_I2O0_HOBDBC, TWS_BIT18, 4);
1076    db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4);
1077
1078}
1079
1080static void
1081tws_intr_attn_error(struct tws_softc *sc)
1082{
1083    u_int32_t db=0;
1084
1085    TWS_TRACE(sc, "attn error", 0, 0);
1086    tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4);
1087    db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4);
1088    device_printf(sc->tws_dev, "Micro controller error.\n");
1089    tws_reset(sc);
1090}
1091
1092static void
1093tws_intr_resp(struct tws_softc *sc)
1094{
1095    u_int16_t req_id;
1096    u_int64_t mfa;
1097
1098    while ( tws_get_response(sc, &req_id, &mfa) ) {
1099        sc->stats.reqs_out++;
1100        if ( req_id == TWS_INVALID_REQID ) {
1101            TWS_TRACE_DEBUG(sc, "invalid req_id", mfa, req_id);
1102            sc->stats.reqs_errored++;
1103            tws_err_complete(sc, mfa);
1104            continue;
1105        }
1106        sc->reqs[req_id].cb(&sc->reqs[req_id]);
1107    }
1108
1109}
1110
1111static void
1112tws_poll(struct cam_sim *sim)
1113{
1114    struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim);
1115    TWS_TRACE_DEBUG(sc, "entry", 0, 0);
1116    tws_intr((void *) sc);
1117}
1118
1119void
1120tws_timeout(void *arg)
1121{
1122    struct tws_request *req = (struct tws_request *)arg;
1123    struct tws_softc *sc = req->sc;
1124
1125    if ( req->error_code == TWS_REQ_RET_RESET ) {
1126        return;
1127    }
1128
1129    mtx_lock(&sc->gen_lock);
1130    if ( req->error_code == TWS_REQ_RET_RESET ) {
1131        mtx_unlock(&sc->gen_lock);
1132        return;
1133    }
1134
1135    if ( tws_get_state(sc) == TWS_RESET ) {
1136        mtx_unlock(&sc->gen_lock);
1137        return;
1138    }
1139
1140    xpt_freeze_simq(sc->sim, 1);
1141
1142    tws_send_event(sc, TWS_RESET_START);
1143
1144    if (req->type == TWS_REQ_TYPE_SCSI_IO) {
1145        device_printf(sc->tws_dev, "I/O Request timed out... Resetting controller\n");
1146    } else if (req->type == TWS_REQ_TYPE_PASSTHRU) {
1147        device_printf(sc->tws_dev, "IOCTL Request timed out... Resetting controller\n");
1148    } else {
1149        device_printf(sc->tws_dev, "Internal Request timed out... Resetting controller\n");
1150    }
1151
1152    tws_assert_soft_reset(sc);
1153    tws_turn_off_interrupts(sc);
1154    tws_reset_cb( (void*) sc );
1155    tws_reinit( (void*) sc );
1156
1157//  device_printf(sc->tws_dev,  "Controller Reset complete!\n");
1158    tws_send_event(sc, TWS_RESET_COMPLETE);
1159    mtx_unlock(&sc->gen_lock);
1160
1161    xpt_release_simq(sc->sim, 1);
1162}
1163
1164void
1165tws_reset(void *arg)
1166{
1167    struct tws_softc *sc = (struct tws_softc *)arg;
1168
1169    mtx_lock(&sc->gen_lock);
1170    if ( tws_get_state(sc) == TWS_RESET ) {
1171        mtx_unlock(&sc->gen_lock);
1172        return;
1173    }
1174
1175    xpt_freeze_simq(sc->sim, 1);
1176
1177    tws_send_event(sc, TWS_RESET_START);
1178
1179    device_printf(sc->tws_dev,  "Resetting controller\n");
1180
1181    tws_assert_soft_reset(sc);
1182    tws_turn_off_interrupts(sc);
1183    tws_reset_cb( (void*) sc );
1184    tws_reinit( (void*) sc );
1185
1186//  device_printf(sc->tws_dev,  "Controller Reset complete!\n");
1187    tws_send_event(sc, TWS_RESET_COMPLETE);
1188    mtx_unlock(&sc->gen_lock);
1189
1190    xpt_release_simq(sc->sim, 1);
1191}
1192
1193static void
1194tws_reset_cb(void *arg)
1195{
1196    struct tws_softc *sc = (struct tws_softc *)arg;
1197    time_t endt;
1198    int found = 0;
1199    u_int32_t reg;
1200
1201    if ( tws_get_state(sc) != TWS_RESET ) {
1202        return;
1203    }
1204
1205//  device_printf(sc->tws_dev,  "Draining Busy Queue\n");
1206    tws_drain_busy_queue(sc);
1207//  device_printf(sc->tws_dev,  "Draining Reserved Reqs\n");
1208    tws_drain_reserved_reqs(sc);
1209//  device_printf(sc->tws_dev,  "Draining Response Queue\n");
1210    tws_drain_response_queue(sc);
1211
1212//  device_printf(sc->tws_dev,  "Looking for controller ready flag...\n");
1213    endt = TWS_LOCAL_TIME + TWS_POLL_TIMEOUT;
1214    while ((TWS_LOCAL_TIME <= endt) && (!found)) {
1215        reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4);
1216        if ( reg & TWS_BIT13 ) {
1217            found = 1;
1218//          device_printf(sc->tws_dev,  " ... Got it!\n");
1219        }
1220    }
1221    if ( !found )
1222            device_printf(sc->tws_dev,  " ... Controller ready flag NOT found!\n");
1223}
1224
1225static void
1226tws_reinit(void *arg)
1227{
1228    struct tws_softc *sc = (struct tws_softc *)arg;
1229    int timeout_val=0;
1230    int try=2;
1231    int done=0;
1232
1233//  device_printf(sc->tws_dev,  "Waiting for Controller Ready\n");
1234    while ( !done && try ) {
1235        if ( tws_ctlr_ready(sc) ) {
1236            done = 1;
1237            break;
1238        } else {
1239            timeout_val += 5;
1240            if ( timeout_val >= TWS_RESET_TIMEOUT ) {
1241               timeout_val = 0;
1242               if ( try )
1243                   tws_assert_soft_reset(sc);
1244               try--;
1245            }
1246            mtx_sleep(sc, &sc->gen_lock, 0, "tws_reinit", 5*hz);
1247        }
1248    }
1249
1250    if (!done) {
1251        device_printf(sc->tws_dev,  "FAILED to get Controller Ready!\n");
1252        return;
1253    }
1254
1255    sc->obfl_q_overrun = false;
1256//  device_printf(sc->tws_dev,  "Sending initConnect\n");
1257    if ( tws_init_connect(sc, tws_queue_depth) ) {
1258        TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit);
1259    }
1260    tws_init_obfl_q(sc);
1261
1262    tws_turn_on_interrupts(sc);
1263
1264    wakeup_one(sc);
1265}
1266
1267static void
1268tws_freeze_simq(struct tws_softc *sc, struct tws_request *req)
1269{
1270    /* Only for IO commands */
1271    if (req->type == TWS_REQ_TYPE_SCSI_IO) {
1272        union ccb   *ccb = (union ccb *)(req->ccb_ptr);
1273
1274        xpt_freeze_simq(sc->sim, 1);
1275        ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1276        ccb->ccb_h.status |= CAM_REQUEUE_REQ;
1277    }
1278}
1279
1280TUNABLE_INT("hw.tws.cam_depth", &tws_cam_depth);
1281