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