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