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