twa(4): Sync with FreeBSD (twa(4) version 3.80.06.003).
[dragonfly.git] / sys / dev / raid / twa / tw_osl_cam.c
1 /*
2  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3  * Copyright (c) 2004-05 Vinod Kashyap.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *      $FreeBSD: src/sys/dev/twa/tw_osl_cam.c,v 1.15 2010/08/30 19:15:04 delphij Exp $
28  */
29
30 /*
31  * AMCC'S 3ware driver for 9000 series storage controllers.
32  *
33  * Author: Vinod Kashyap
34  * Modifications by: Adam Radford
35  * Modifications by: Manjunath Ranganathaiah
36  */
37
38
39 /*
40  * FreeBSD CAM related functions.
41  */
42
43
44 #include <dev/raid/twa/tw_osl_includes.h>
45
46 #include <bus/cam/cam.h>
47 #include <bus/cam/cam_ccb.h>
48 #include <bus/cam/cam_sim.h>
49 #include <bus/cam/cam_xpt_sim.h>
50 #include <bus/cam/cam_debug.h>
51 #include <bus/cam/cam_periph.h>
52 #include <bus/cam/cam_xpt_periph.h>
53
54 #include <bus/cam/scsi/scsi_all.h>
55 #include <bus/cam/scsi/scsi_message.h>
56
57 static TW_VOID  twa_action(struct cam_sim *sim, union ccb *ccb);
58 static TW_VOID  twa_poll(struct cam_sim *sim);
59 static TW_VOID  twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
60
61 static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
62         union ccb *ccb);
63
64
65
66 /*
67  * Function name:       tw_osli_cam_attach
68  * Description:         Attaches the driver to CAM.
69  *
70  * Input:               sc      -- ptr to OSL internal ctlr context
71  * Output:              None
72  * Return value:        0       -- success
73  *                      non-zero-- failure
74  */
75 TW_INT32
76 tw_osli_cam_attach(struct twa_softc *sc)
77 {
78         struct cam_devq         *devq;
79
80         tw_osli_dbg_dprintf(3, sc, "entered");
81
82         /*
83          * Create the device queue for our SIM.
84          */
85         if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
86                 tw_osli_printf(sc, "error = %d",
87                         TW_CL_SEVERITY_ERROR_STRING,
88                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
89                         0x2100,
90                         "Failed to create SIM device queue",
91                         ENOMEM);
92                 return(ENOMEM);
93         }
94
95         /*
96          * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
97          * simultaneous requests, we claim to be able to handle only
98          * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
99          * packet available to service ioctls and AENs.
100          */
101         tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
102         sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
103                         device_get_unit(sc->bus_dev), sc->sim_lock,
104                         TW_OSLI_MAX_NUM_IOS, 1, devq);
105         if (sc->sim == NULL) {
106                 tw_osli_printf(sc, "error = %d",
107                         TW_CL_SEVERITY_ERROR_STRING,
108                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
109                         0x2101,
110                         "Failed to create a SIM entry",
111                         ENOMEM);
112                 return(ENOMEM);
113         }
114
115         /*
116          * Register the bus.
117          */
118         tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
119         lockmgr(sc->sim_lock, LK_EXCLUSIVE);
120         if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
121                 cam_sim_free(sc->sim);
122                 sc->sim = NULL; /* so cam_detach will not try to free it */
123                 tw_osli_printf(sc, "error = %d",
124                         TW_CL_SEVERITY_ERROR_STRING,
125                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
126                         0x2102,
127                         "Failed to register the bus",
128                         ENXIO);
129                 lockmgr(sc->sim_lock, LK_RELEASE);
130                 return(ENXIO);
131         }
132
133         tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
134         if (xpt_create_path(&sc->path, NULL,
135                                 cam_sim_path(sc->sim),
136                                 CAM_TARGET_WILDCARD,
137                                 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
138                 xpt_bus_deregister(cam_sim_path (sc->sim));
139                 /* Passing TRUE to cam_sim_free will free the devq as well. */
140                 cam_sim_free(sc->sim);
141                 tw_osli_printf(sc, "error = %d",
142                         TW_CL_SEVERITY_ERROR_STRING,
143                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
144                         0x2103,
145                         "Failed to create path",
146                         ENXIO);
147                 lockmgr(sc->sim_lock, LK_RELEASE);
148                 return(ENXIO);
149         }
150         lockmgr(sc->sim_lock, LK_RELEASE);
151
152         tw_osli_dbg_dprintf(3, sc, "exiting");
153         return(0);
154 }
155
156
157
158 /*
159  * Function name:       tw_osli_cam_detach
160  * Description:         Detaches the driver from CAM.
161  *
162  * Input:               sc      -- ptr to OSL internal ctlr context
163  * Output:              None
164  * Return value:        None
165  */
166 TW_VOID
167 tw_osli_cam_detach(struct twa_softc *sc)
168 {
169         tw_osli_dbg_dprintf(3, sc, "entered");
170
171         lockmgr(sc->sim_lock, LK_EXCLUSIVE);
172
173         if (sc->path)
174                 xpt_free_path(sc->path);
175         if (sc->sim) {
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);
179         }
180         /* It's ok have 1 hold count while destroying the mutex */
181         lockuninit(sc->sim_lock);
182 }
183
184
185
186 /*
187  * Function name:       tw_osli_execute_scsi
188  * Description:         Build a fw cmd, based on a CAM style ccb, and
189  *                      send it down.
190  *
191  * Input:               req     -- ptr to OSL internal request context
192  *                      ccb     -- ptr to CAM style ccb
193  * Output:              None
194  * Return value:        0       -- success
195  *                      non-zero-- failure
196  */
197 TW_INT32
198 tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
199 {
200         struct twa_softc                *sc = req->ctlr;
201         struct tw_cl_req_packet         *req_pkt;
202         struct tw_cl_scsi_req_packet    *scsi_req;
203         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
204         struct ccb_scsiio               *csio = &(ccb->csio);
205         TW_INT32                        error;
206
207         tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
208                 csio->cdb_io.cdb_bytes[0]);
209
210         if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
211                 tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
212                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
213                 ccb_h->status |= CAM_TID_INVALID;
214                 xpt_done(ccb);
215                 return(1);
216         }
217         if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
218                 tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
219                         ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
220                 ccb_h->status |= CAM_LUN_INVALID;
221                 xpt_done(ccb);
222                 return(1);
223         }
224
225         if(ccb_h->flags & CAM_CDB_PHYS) {
226                 tw_osli_printf(sc, "",
227                         TW_CL_SEVERITY_ERROR_STRING,
228                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
229                         0x2105,
230                         "Physical CDB address!");
231                 ccb_h->status = CAM_REQ_INVALID;
232                 xpt_done(ccb);
233                 return(1);
234         }
235
236         /*
237          * We are going to work on this request.  Mark it as enqueued (though
238          * we don't actually queue it...)
239          */
240         ccb_h->status |= CAM_SIM_QUEUED;
241
242         if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
243                 if(ccb_h->flags & CAM_DIR_IN)
244                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
245                 else
246                         req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
247         }
248
249         /* Build the CL understood request packet for SCSI cmds. */
250         req_pkt = &req->req_pkt;
251         req_pkt->status = 0;
252         req_pkt->tw_osl_callback = tw_osl_complete_io;
253         scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
254         scsi_req->unit = ccb_h->target_id;
255         scsi_req->lun = ccb_h->target_lun;
256         scsi_req->sense_len = 0;
257         scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
258         scsi_req->scsi_status = 0;
259         if(ccb_h->flags & CAM_CDB_POINTER)
260                 scsi_req->cdb = csio->cdb_io.cdb_ptr;
261         else
262                 scsi_req->cdb = csio->cdb_io.cdb_bytes;
263         scsi_req->cdb_len = csio->cdb_len;
264
265         if (!(ccb_h->flags & CAM_DATA_PHYS)) {
266                 /* Virtual data addresses.  Need to convert them... */
267                 tw_osli_dbg_dprintf(3, sc,
268                         "XPT_SCSI_IO: Single virtual address!");
269                 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
270                         if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
271                                 tw_osli_printf(sc, "size = %d",
272                                         TW_CL_SEVERITY_ERROR_STRING,
273                                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
274                                         0x2106,
275                                         "I/O size too big",
276                                         csio->dxfer_len);
277                                 ccb_h->status = CAM_REQ_TOO_BIG;
278                                 ccb_h->status &= ~CAM_SIM_QUEUED;
279                                 xpt_done(ccb);
280                                 return(1);
281                         }
282
283                         if ((req->length = csio->dxfer_len)) {
284                                 req->data = csio->data_ptr;
285                                 scsi_req->sgl_entries = 1;
286                         }
287                 } else {
288                         tw_osli_printf(sc, "",
289                                 TW_CL_SEVERITY_ERROR_STRING,
290                                 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
291                                 0x2107,
292                                 "XPT_SCSI_IO: Got SGList");
293                         ccb_h->status = CAM_REQ_INVALID;
294                         ccb_h->status &= ~CAM_SIM_QUEUED;
295                         xpt_done(ccb);
296                         return(1);
297                 }
298         } else {
299                 /* Data addresses are physical. */
300                 tw_osli_printf(sc, "",
301                         TW_CL_SEVERITY_ERROR_STRING,
302                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
303                         0x2108,
304                         "XPT_SCSI_IO: Physical data addresses");
305                 ccb_h->status = CAM_REQ_INVALID;
306                 ccb_h->status &= ~CAM_SIM_QUEUED;
307                 xpt_done(ccb);
308                 return(1);
309         }
310
311         req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
312
313
314         /*
315          * twa_map_load_data_callback will fill in the SGL,
316          * and submit the I/O.
317          */
318         error = tw_osli_map_request(req);
319         if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
320                 req->deadline = 0;
321                 ccb_h->status = CAM_REQ_CMP_ERR;
322                 ccb_h->status &= ~CAM_SIM_QUEUED;
323                 xpt_done(ccb);
324         }
325         return(error);
326 }
327
328
329
330 /*
331  * Function name:       twa_action
332  * Description:         Driver entry point for CAM's use.
333  *
334  * Input:               sim     -- sim corresponding to the ctlr
335  *                      ccb     -- ptr to CAM request
336  * Output:              None
337  * Return value:        None
338  */
339 TW_VOID
340 twa_action(struct cam_sim *sim, union ccb *ccb)
341 {
342         struct twa_softc        *sc = (struct twa_softc *)cam_sim_softc(sim);
343         struct ccb_hdr          *ccb_h = &(ccb->ccb_h);
344
345         switch (ccb_h->func_code) {
346         case XPT_SCSI_IO:       /* SCSI I/O */
347         {
348                 struct tw_osli_req_context      *req;
349
350                 req = tw_osli_get_request(sc);
351                 if (req == NULL) {
352                         tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
353                         /*
354                          * Freeze the simq to maintain ccb ordering.  The next
355                          * ccb that gets completed will unfreeze the simq.
356                          */
357                         ccb_h->status &= ~CAM_SIM_QUEUED;
358                         ccb_h->status |= CAM_REQUEUE_REQ;
359                         xpt_done(ccb);
360                         break;
361                 }
362
363                 if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
364                         ccb_h->status &= ~CAM_SIM_QUEUED;
365                         ccb_h->status |= CAM_REQUEUE_REQ;
366                         xpt_done(ccb);
367                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
368                         break;
369                 }
370
371                 req->req_handle.osl_req_ctxt = req;
372                 req->req_handle.is_io = TW_CL_TRUE;
373                 req->orig_req = ccb;
374                 if (tw_osli_execute_scsi(req, ccb))
375                         tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
376                 break;
377         }
378
379         case XPT_ABORT:
380                 tw_osli_dbg_dprintf(2, sc, "Abort request.");
381                 ccb_h->status = CAM_UA_ABORT;
382                 xpt_done(ccb);
383                 break;
384
385         case XPT_RESET_BUS:
386                 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
387                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
388                         0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
389                         "Received Reset Bus request from CAM",
390                         " ");
391
392                 tw_cl_set_reset_needed(&(sc->ctlr_handle));
393                 ccb_h->status = CAM_REQ_CMP;
394                 xpt_done(ccb);
395                 break;
396
397         case XPT_SET_TRAN_SETTINGS:
398                 tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
399
400                 /*
401                  * This command is not supported, since it's very specific
402                  * to SCSI, and we are doing ATA.
403                  */
404                 ccb_h->status = CAM_FUNC_NOTAVAIL;
405                 xpt_done(ccb);
406                 break;
407
408         case XPT_GET_TRAN_SETTINGS:
409         {
410                 struct ccb_trans_settings       *cts = &ccb->cts;
411                 struct ccb_trans_settings_scsi *scsi =
412                     &cts->proto_specific.scsi;
413                 struct ccb_trans_settings_spi *spi =
414                     &cts->xport_specific.spi;
415
416                 cts->protocol = PROTO_SCSI;
417                 cts->protocol_version = SCSI_REV_2;
418                 cts->transport = XPORT_SPI;
419                 cts->transport_version = 2;
420
421                 spi->valid = CTS_SPI_VALID_DISC;
422                 spi->flags = CTS_SPI_FLAGS_DISC_ENB;
423                 scsi->valid = CTS_SCSI_VALID_TQ;
424                 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
425                 tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
426                 ccb_h->status = CAM_REQ_CMP;
427                 xpt_done(ccb);
428                 break;
429         }
430
431         case XPT_CALC_GEOMETRY:
432                 tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
433                 cam_calc_geometry(&ccb->ccg, 1/* extended */);
434                 xpt_done(ccb);
435                 break;
436
437         case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
438         {
439                 struct ccb_pathinq      *path_inq = &ccb->cpi;
440
441                 tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
442
443                 path_inq->version_num = 1;
444                 path_inq->hba_inquiry = 0;
445                 path_inq->target_sprt = 0;
446                 path_inq->hba_misc = 0;
447                 path_inq->hba_eng_cnt = 0;
448                 path_inq->max_target = TW_CL_MAX_NUM_UNITS;
449                 path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
450                 path_inq->unit_number = cam_sim_unit(sim);
451                 path_inq->bus_id = cam_sim_bus(sim);
452                 path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
453                 path_inq->base_transfer_speed = 100000;
454                 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
455                 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
456                 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
457                 path_inq->transport = XPORT_SPI;
458                 path_inq->transport_version = 2;
459                 path_inq->protocol = PROTO_SCSI;
460                 path_inq->protocol_version = SCSI_REV_2;
461 #if 0 /* XXX swildner */
462                 path_inq->maxio = TW_CL_MAX_IO_SIZE;
463 #endif
464                 ccb_h->status = CAM_REQ_CMP;
465                 xpt_done(ccb);
466                 break;
467         }
468
469         default:
470                 tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
471                 ccb_h->status = CAM_REQ_INVALID;
472                 xpt_done(ccb);
473                 break;
474         }
475 }
476
477
478
479 /*
480  * Function name:       twa_poll
481  * Description:         Driver entry point called when interrupts are not
482  *                      available.
483  *
484  * Input:               sim     -- sim corresponding to the controller
485  * Output:              None
486  * Return value:        None
487  */
488 TW_VOID
489 twa_poll(struct cam_sim *sim)
490 {
491         struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
492
493         tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
494         tw_cl_interrupt(&(sc->ctlr_handle));
495         tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
496 }
497
498
499
500 /*
501  * Function name:       tw_osli_request_bus_scan
502  * Description:         Requests CAM for a scan of the bus.
503  *
504  * Input:               sc      -- ptr to per ctlr structure
505  * Output:              None
506  * Return value:        0       -- success
507  *                      non-zero-- failure
508  */
509 TW_INT32
510 tw_osli_request_bus_scan(struct twa_softc *sc)
511 {
512         union ccb       *ccb;
513
514         tw_osli_dbg_dprintf(3, sc, "entering");
515
516         /* If we get here before sc->sim is initialized, return an error. */
517         if (!(sc->sim))
518                 return(ENXIO);
519         if ((ccb = xpt_alloc_ccb()) == NULL)
520                 return(ENOMEM);
521         lockmgr(sc->sim_lock, LK_EXCLUSIVE);
522         if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
523             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
524                 xpt_free_ccb(ccb);
525                 lockmgr(sc->sim_lock, LK_RELEASE);
526                 return(EIO);
527         }
528
529         xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
530         ccb->ccb_h.func_code = XPT_SCAN_BUS;
531         ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
532         ccb->crcn.flags = CAM_FLAG_NONE;
533         xpt_action(ccb);
534
535         lockmgr(sc->sim_lock, LK_RELEASE);
536         return(0);
537 }
538
539
540
541 /*
542  * Function name:       twa_bus_scan_cb
543  * Description:         Callback from CAM on a bus scan request.
544  *
545  * Input:               periph  -- we don't use this
546  *                      ccb     -- bus scan request ccb that we sent to CAM
547  * Output:              None
548  * Return value:        None
549  */
550 static TW_VOID
551 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
552 {
553         tw_osli_dbg_printf(3, "entering");
554
555         if (ccb->ccb_h.status != CAM_REQ_CMP)
556                 kprintf("cam_scan_callback: failure status = %x\n",
557                         ccb->ccb_h.status);
558         else
559                 tw_osli_dbg_printf(3, "success");
560
561         xpt_free_path(ccb->ccb_h.path);
562         kfree(ccb, M_TEMP);
563 }
564
565
566
567 /*
568  * Function name:       tw_osli_disallow_new_requests
569  * Description:         Calls the appropriate CAM function, so as to freeze
570  *                      the flow of new requests from CAM to this controller.
571  *
572  * Input:               sc      -- ptr to OSL internal ctlr context
573  *                      req_handle -- ptr to request handle sent by OSL.
574  * Output:              None
575  * Return value:        None
576  */
577 TW_VOID
578 tw_osli_disallow_new_requests(struct twa_softc *sc,
579         struct tw_cl_req_handle *req_handle)
580 {
581         /* Only freeze/release the simq for IOs */
582         if (req_handle->is_io) {
583                 struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
584                 union ccb                       *ccb = (union ccb *)(req->orig_req);
585
586                 xpt_freeze_simq(sc->sim, 1);
587                 ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
588         }
589 }
590
591
592
593 /*
594  * Function name:       tw_osl_timeout
595  * Description:         Call to timeout().
596  *
597  * Input:               req_handle -- ptr to request handle sent by OSL.
598  * Output:              None
599  * Return value:        None
600  */
601 TW_VOID
602 tw_osl_timeout(struct tw_cl_req_handle *req_handle)
603 {
604         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
605         union ccb                       *ccb = (union ccb *)(req->orig_req);
606         struct ccb_hdr                  *ccb_h = &(ccb->ccb_h);
607
608         req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
609 }
610
611
612
613 /*
614  * Function name:       tw_osl_untimeout
615  * Description:         Inverse of call to timeout().
616  *
617  * Input:               req_handle -- ptr to request handle sent by OSL.
618  * Output:              None
619  * Return value:        None
620  */
621 TW_VOID
622 tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
623 {
624         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
625
626         req->deadline = 0;
627 }
628
629
630
631 /*
632  * Function name:       tw_osl_scan_bus
633  * Description:         CL calls this function to request for a bus scan.
634  *
635  * Input:               ctlr_handle     -- ptr to controller handle
636  * Output:              None
637  * Return value:        None
638  */
639 TW_VOID
640 tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
641 {
642         struct twa_softc        *sc = ctlr_handle->osl_ctlr_ctxt;
643         TW_INT32                error;
644
645         if ((error = tw_osli_request_bus_scan(sc)))
646                 tw_osli_printf(sc, "error = %d",
647                         TW_CL_SEVERITY_ERROR_STRING,
648                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
649                         0x2109,
650                         "Bus scan request to CAM failed",
651                         error);
652 }
653
654
655
656 /*
657  * Function name:       tw_osl_complete_io
658  * Description:         Called to complete CAM scsi requests.
659  *
660  * Input:               req_handle      -- ptr to request handle
661  * Output:              None
662  * Return value:        None
663  */
664 TW_VOID
665 tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
666 {
667         struct tw_osli_req_context      *req = req_handle->osl_req_ctxt;
668         struct tw_cl_req_packet         *req_pkt =
669                 (struct tw_cl_req_packet *)(&req->req_pkt);
670         struct tw_cl_scsi_req_packet    *scsi_req;
671         struct twa_softc                *sc = req->ctlr;
672         union ccb                       *ccb = (union ccb *)(req->orig_req);
673
674         tw_osli_dbg_dprintf(10, sc, "entering");
675
676         if (req->state != TW_OSLI_REQ_STATE_BUSY)
677                 tw_osli_printf(sc, "request = %p, status = %d",
678                         TW_CL_SEVERITY_ERROR_STRING,
679                         TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
680                         0x210A,
681                         "Unposted command completed!!",
682                         req, req->state);
683
684         /*
685          * Remove request from the busy queue.  Just mark it complete.
686          * There's no need to move it into the complete queue as we are
687          * going to be done with it right now.
688          */
689         req->state = TW_OSLI_REQ_STATE_COMPLETE;
690         tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
691
692         tw_osli_unmap_request(req);
693
694         req->deadline = 0;
695         if (req->error_code) {
696                 /* This request never got submitted to the firmware. */
697                 if (req->error_code == EBUSY) {
698                         /*
699                          * Cmd queue is full, or the Common Layer is out of
700                          * resources.  The simq will already have been frozen.
701                          * When this ccb gets completed will unfreeze the simq.
702                          */
703                         ccb->ccb_h.status |= CAM_REQUEUE_REQ;
704                 }
705                 else if (req->error_code == EFBIG)
706                         ccb->ccb_h.status = CAM_REQ_TOO_BIG;
707                 else
708                         ccb->ccb_h.status = CAM_REQ_CMP_ERR;
709         } else {
710                 scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
711                 if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
712                         ccb->ccb_h.status = CAM_REQ_CMP;
713                 else {
714                         if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
715                                 ccb->ccb_h.status |= CAM_TID_INVALID;
716                         else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
717                                 ccb->ccb_h.status |= CAM_LUN_INVALID;
718                         else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
719                                 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
720                         else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
721                                 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
722                         /*
723                          * If none of the above errors occurred, simply
724                          * mark completion error.
725                          */
726                         if (ccb->ccb_h.status == 0)
727                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
728
729                         if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
730                                 ccb->csio.sense_len = scsi_req->sense_len;
731                                 ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
732                         }
733                 }
734
735                 ccb->csio.scsi_status = scsi_req->scsi_status;
736         }
737
738         ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
739         lockmgr(sc->sim_lock, LK_EXCLUSIVE);
740         xpt_done(ccb);
741         lockmgr(sc->sim_lock, LK_RELEASE);
742         if (! req->error_code)
743                  /* twa_action will free the request otherwise */
744                 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
745 }