FreeBSD/Linux Kernel Cross Reference
sys/dev/twa/twa_cam.c
1 /*-
2 * Copyright (c) 2003-04 3ware, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29 /*
30 * 3ware driver for 9000 series storage controllers.
31 *
32 * Author: Vinod Kashyap
33 */
34
35
36 #include <dev/twa/twa_includes.h>
37
38 #include <cam/cam.h>
39 #include <cam/cam_ccb.h>
40 #include <cam/cam_sim.h>
41 #include <cam/cam_xpt_sim.h>
42 #include <cam/cam_xpt_periph.h>
43 #include <cam/cam_debug.h>
44 #include <cam/cam_periph.h>
45
46 #include <cam/scsi/scsi_all.h>
47 #include <cam/scsi/scsi_message.h>
48
49 static int twa_execute_scsi(struct twa_request *tr, union ccb *ccb);
50 static void twa_action(struct cam_sim *sim, union ccb *ccb);
51 static void twa_poll(struct cam_sim *sim);
52 static void twa_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg);
53 static void twa_timeout(void *arg);
54 static void twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
55
56
57
58 /*
59 * Function name: twa_cam_setup
60 * Description: Attaches the driver to CAM.
61 *
62 * Input: sc -- ptr to per ctlr structure
63 * Output: None
64 * Return value: 0 -- success
65 * non-zero-- failure
66 */
67 int
68 twa_cam_setup(struct twa_softc *sc)
69 {
70 struct cam_devq *devq;
71 struct ccb_setasync csa;
72
73 twa_dbg_dprint(3, sc, "sc = %p", sc);
74 /*
75 * Create the device queue for our SIM.
76 */
77 devq = cam_simq_alloc(TWA_Q_LENGTH);
78 if (devq == NULL)
79 return(ENOMEM);
80
81 /*
82 * Create a SIM entry. Though we can support TWA_Q_LENGTH simultaneous
83 * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so
84 * that we always have a request packet available to service attention
85 * interrupts.
86 */
87 twa_dbg_dprint(3, sc, "Calling cam_sim_alloc");
88 sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
89 device_get_unit(sc->twa_bus_dev),
90 TWA_Q_LENGTH - 1, 1, devq);
91 if (sc->twa_sim == NULL) {
92 cam_simq_free(devq);
93 return(ENOMEM);
94 }
95
96 /*
97 * Register the bus.
98 */
99 twa_dbg_dprint(3, sc, "Calling xpt_bus_register");
100 if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) {
101 cam_sim_free(sc->twa_sim, TRUE);
102 sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */
103 return(ENXIO);
104 }
105
106 twa_dbg_dprint(3, sc, "Calling xpt_create_path");
107 if (xpt_create_path(&sc->twa_path, NULL,
108 cam_sim_path(sc->twa_sim),
109 CAM_TARGET_WILDCARD,
110 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
111 xpt_bus_deregister(cam_sim_path (sc->twa_sim));
112 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
113 return(ENXIO);
114 }
115
116 twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb");
117 xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5);
118 csa.ccb_h.func_code = XPT_SASYNC_CB;
119 csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
120 csa.callback = twa_async;
121 csa.callback_arg = sc;
122 xpt_action((union ccb *)&csa);
123
124 twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan");
125 /*
126 * Request a bus scan, so that CAM gets to know of
127 * the logical units that we control.
128 */
129 twa_request_bus_scan(sc);
130 twa_dbg_dprint(3, sc, "Exiting");
131 return(0);
132 }
133
134
135
136 /*
137 * Function name: twa_cam_detach
138 * Description: Detaches the driver from CAM.
139 *
140 * Input: sc -- ptr to per ctlr structure
141 * Output: None
142 * Return value: None
143 */
144 void
145 twa_cam_detach(struct twa_softc *sc)
146 {
147 if (sc->twa_path)
148 xpt_free_path(sc->twa_path);
149 if (sc->twa_sim) {
150 xpt_bus_deregister(cam_sim_path(sc->twa_sim));
151 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
152 }
153 }
154
155
156
157 /*
158 * Function name: twa_send_scsi_cmd
159 * Description: Sends down a scsi cmd to fw.
160 *
161 * Input: tr -- ptr to request pkt
162 * cmd -- opcode of scsi cmd to send
163 * Output: None
164 * Return value: 0 -- success
165 * non-zero-- failure
166 */
167 int
168 twa_send_scsi_cmd(struct twa_request *tr, int cmd)
169 {
170 union ccb ccb;
171
172 bzero(&ccb, sizeof(union ccb));
173 ccb.csio.cdb_io.cdb_bytes[0] = (u_int8_t)cmd;
174 ccb.csio.cdb_io.cdb_bytes[4] = 128;
175 ccb.csio.cdb_len = 16;
176 if ((ccb.csio.data_ptr = malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT))
177 == NULL)
178 return(ENOMEM);
179 bzero(ccb.csio.data_ptr, TWA_SECTOR_SIZE);
180 ccb.csio.dxfer_len = TWA_SECTOR_SIZE;
181
182 ccb.ccb_h.target_id = 0;
183 ccb.ccb_h.flags |= CAM_DIR_IN;
184
185 if (twa_execute_scsi(tr, &ccb))
186 return(EIO);
187 return(0);
188 }
189
190
191
192 /*
193 * Function name: twa_execute_scsi
194 * Description: Build a fw cmd, based on a CAM style ccb, and
195 * send it down.
196 *
197 * Input: tr -- ptr to request pkt
198 * ccb -- ptr to CAM style ccb
199 * Output: None
200 * Return value: 0 -- success
201 * non-zero-- failure
202 */
203 int
204 twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
205 {
206 struct twa_softc *sc = tr->tr_sc;
207 struct twa_command_packet *cmdpkt;
208 struct twa_command_9k *cmd9k;
209 struct ccb_hdr *ccb_h = &(ccb->ccb_h);
210 struct ccb_scsiio *csio = &(ccb->csio);
211 int error;
212
213 twa_dbg_dprint(3, sc, "SCSI I/O request 0x%x",
214 csio->cdb_io.cdb_bytes[0]);
215
216 if (ccb_h->target_id >= TWA_MAX_UNITS) {
217 twa_dbg_dprint(3, sc, "Invalid target. PTL = %x %x %x",
218 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
219 ccb_h->status |= CAM_TID_INVALID;
220 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
221 xpt_done(ccb);
222 return(1);
223 }
224 if (ccb_h->target_lun != 0) {
225 twa_dbg_dprint(3, sc, "Invalid lun. PTL = %x %x %x",
226 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
227 ccb_h->status |= CAM_LUN_INVALID;
228 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
229 xpt_done(ccb);
230 return(1);
231 }
232
233 if(ccb_h->flags & CAM_CDB_PHYS) {
234 twa_printf(sc, "Physical CDB address!\n");
235 ccb_h->status = CAM_REQ_CMP_ERR;
236 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
237 xpt_done(ccb);
238 return(1);
239 }
240
241 /*
242 * We are going to work on this request. Mark it as enqueued (though
243 * we don't actually queue it...)
244 */
245 ccb_h->status |= CAM_SIM_QUEUED;
246
247 if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
248 if(ccb_h->flags & CAM_DIR_IN)
249 tr->tr_flags |= TWA_CMD_DATA_IN;
250 else
251 tr->tr_flags |= TWA_CMD_DATA_OUT;
252 }
253
254 cmdpkt = tr->tr_command;
255
256 cmdpkt->cmd_hdr.header_desc.size_header = 128;
257
258 cmd9k = &(cmdpkt->command.cmd_pkt_9k);
259 cmd9k->command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND;
260 cmd9k->unit = ccb_h->target_id;
261 cmd9k->request_id = tr->tr_request_id;
262 cmd9k->status = 0;
263 cmd9k->sgl_offset = 16; /* offset from end of hdr = max cdb len */
264
265 if(ccb_h->flags & CAM_CDB_POINTER)
266 bcopy(csio->cdb_io.cdb_ptr, cmd9k->cdb, csio->cdb_len);
267 else
268 bcopy(csio->cdb_io.cdb_bytes, cmd9k->cdb, csio->cdb_len);
269
270 if (!(ccb_h->flags & CAM_DATA_PHYS)) {
271 /* Virtual data addresses. Need to convert them... */
272 twa_dbg_dprint(3, sc, "XPT_SCSI_IO: Single virtual address!");
273 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
274 if (csio->dxfer_len > TWA_MAX_IO_SIZE) {
275 twa_printf(sc, "I/O size %d too big.\n",
276 csio->dxfer_len);
277 ccb_h->status = CAM_REQ_TOO_BIG;
278 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
279 xpt_done(ccb);
280 return(1);
281 }
282
283 if ((tr->tr_length = csio->dxfer_len)) {
284 tr->tr_data = csio->data_ptr;
285 cmd9k->sgl_entries = 1;
286 }
287 } else {
288 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
289 ccb_h->status = CAM_REQ_CMP_ERR;
290 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
291 xpt_done(ccb);
292 }
293 return(1);
294 }
295 } else {
296 /* Data addresses are physical. */
297 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
298 ccb_h->status = CAM_REQ_CMP_ERR;
299 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
300 ccb_h->status |= CAM_RELEASE_SIMQ;
301 ccb_h->status &= ~CAM_SIM_QUEUED;
302 xpt_done(ccb);
303 }
304 return(1);
305 }
306
307 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
308
309 twa_set_timer(tr);
310
311 /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
312 error = twa_map_request(tr);
313 return(error);
314 }
315
316
317
318 /*
319 * Function name: twa_action
320 * Description: Driver entry point for CAM's use.
321 *
322 * Input: sim -- sim corresponding to the ctlr
323 * ccb -- ptr to CAM request
324 * Output: None
325 * Return value: None
326 */
327 void
328 twa_action(struct cam_sim *sim, union ccb *ccb)
329 {
330 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
331 struct ccb_hdr *ccb_h = &(ccb->ccb_h);
332
333 switch (ccb_h->func_code) {
334 case XPT_SCSI_IO: /* SCSI I/O */
335 {
336 struct twa_request *tr;
337
338 if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
339 ((tr = twa_get_request(sc)) == NULL)) {
340 twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
341 /*
342 * Freeze the simq to maintain ccb ordering. The next
343 * ccb that gets completed will unfreeze the simq.
344 */
345 twa_disallow_new_requests(sc);
346 ccb_h->status |= CAM_REQUEUE_REQ;
347 xpt_done(ccb);
348 break;
349 }
350 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
351 tr->tr_private = ccb;
352 tr->tr_callback = twa_complete_io;
353 if (twa_execute_scsi(tr, ccb))
354 twa_release_request(tr);
355 break;
356 }
357
358 case XPT_ABORT:
359 twa_dbg_dprint(2, sc, "Abort request");
360 ccb_h->status = CAM_UA_ABORT;
361 xpt_done(ccb);
362 break;
363
364 case XPT_RESET_BUS:
365 twa_printf(sc, "Reset Bus request from CAM...\n");
366 if (twa_reset(sc)) {
367 twa_printf(sc, "Reset Bus failed!\n");
368 ccb_h->status = CAM_REQ_CMP_ERR;
369 }
370 else
371 ccb_h->status = CAM_REQ_CMP;
372
373 xpt_done(ccb);
374 break;
375
376 case XPT_SET_TRAN_SETTINGS:
377 twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS");
378
379 /*
380 * This command is not supported, since it's very specific
381 * to SCSI, and we are doing ATA.
382 */
383 ccb_h->status = CAM_FUNC_NOTAVAIL;
384 xpt_done(ccb);
385 break;
386
387 case XPT_GET_TRAN_SETTINGS:
388 {
389 struct ccb_trans_settings *cts = &ccb->cts;
390
391 twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
392 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
393 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
394 ccb_h->status = CAM_REQ_CMP;
395 xpt_done(ccb);
396 break;
397 }
398
399 case XPT_CALC_GEOMETRY:
400 {
401 struct ccb_calc_geometry *geom;
402
403 twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
404 geom = &ccb->ccg;
405
406 if (geom->volume_size > 0x200000) /* 1 GB */ {
407 geom->heads = 255;
408 geom->secs_per_track = 63;
409 } else {
410 geom->heads = 64;
411 geom->secs_per_track = 32;
412 }
413 geom->cylinders = geom->volume_size /
414 (geom->heads * geom->secs_per_track);
415 ccb_h->status = CAM_REQ_CMP;
416 xpt_done(ccb);
417 break;
418 }
419
420 case XPT_PATH_INQ: /* Path inquiry -- get twa properties */
421 {
422 struct ccb_pathinq *path_inq = &ccb->cpi;
423
424 twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
425
426 path_inq->version_num = 1;
427 path_inq->hba_inquiry = PI_WIDE_16;
428 path_inq->target_sprt = 0;
429 path_inq->hba_misc |= PIM_NOBUSRESET;
430 path_inq->hba_eng_cnt = 0;
431 path_inq->max_target = TWA_MAX_UNITS;
432 path_inq->max_lun = 0;
433 path_inq->unit_number = cam_sim_unit(sim);
434 path_inq->bus_id = cam_sim_bus(sim);
435 path_inq->initiator_id = 12;
436 path_inq->base_transfer_speed = 100000;
437 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
438 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
439 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
440 ccb_h->status = CAM_REQ_CMP;
441 xpt_done(ccb);
442 break;
443 }
444
445 default:
446 twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
447 ccb_h->status = CAM_REQ_INVALID;
448 xpt_done(ccb);
449 break;
450 }
451 }
452
453
454
455 /*
456 * Function name: twa_poll
457 * Description: Driver entry point called when interrupts are not available.
458 *
459 * Input: sim -- sim corresponding to the controller
460 * Output: None
461 * Return value: None
462 */
463 void
464 twa_poll(struct cam_sim *sim)
465 {
466 #ifdef TWA_DEBUG
467 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
468 #endif /* TWA_DEBUG */
469
470 twa_dbg_dprint(3, sc, "Entering sc = %p", sc);
471 twa_interrupt(cam_sim_softc(sim));
472 twa_dbg_dprint(3, sc, "Exiting sc = %p", sc);
473 }
474
475
476
477 /*
478 * Function name: twa_async
479 * Description: Driver entry point for CAM to notify driver of special
480 * events. We don't use this for now.
481 *
482 * Input: callback_arg -- ptr to per ctlr structure
483 * code -- code associated with the event
484 * path -- cam path
485 * arg --
486 * Output: None
487 * Return value: 0 -- success
488 * non-zero-- failure
489 */
490 void
491 twa_async(void *callback_arg, u_int32_t code,
492 struct cam_path *path, void *arg)
493 {
494 #ifdef TWA_DEBUG
495 struct twa_softc *sc = (struct twa_softc *)callback_arg;
496 #endif /* TWA_DEBUG */
497
498 twa_dbg_dprint(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
499 sc, code, path, arg);
500 }
501
502
503
504 /*
505 * Function name: twa_timeout
506 * Description: Driver entry point for being alerted on a request
507 * timing out.
508 *
509 * Input: arg -- ptr to timed out request
510 * Output: None
511 * Return value: None
512 */
513 static void
514 twa_timeout(void *arg)
515 {
516 struct twa_request *tr = (struct twa_request *)arg;
517 struct twa_softc *sc = (struct twa_softc *)(tr->tr_sc);
518
519 twa_printf(sc, "Request timed out! tr = %p\n", tr);
520
521 twa_reset(sc);
522 }
523
524
525
526 /*
527 * Function name: twa_request_bus_scan
528 * Description: Requests CAM for a scan of the bus.
529 *
530 * Input: sc -- ptr to per ctlr structure
531 * Output: None
532 * Return value: None
533 */
534 void
535 twa_request_bus_scan(struct twa_softc *sc)
536 {
537 struct cam_path *path;
538 union ccb *ccb;
539
540 if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
541 return;
542 bzero(ccb, sizeof(union ccb));
543 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->twa_sim),
544 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
545 return;
546
547 xpt_setup_ccb(&ccb->ccb_h, path, 5);
548 ccb->ccb_h.func_code = XPT_SCAN_BUS;
549 ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
550 ccb->crcn.flags = CAM_FLAG_NONE;
551 xpt_action(ccb);
552 }
553
554
555
556 /*
557 * Function name: twa_bus_scan_cb
558 * Description: Callback from CAM on a bus scan request.
559 *
560 * Input: periph -- we don't use this
561 * ccb -- bus scan request ccb that we sent to CAM
562 * Output: None
563 * Return value: None
564 */
565 static void
566 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
567 {
568 twa_dbg_print(3, "ccb = %p\n", ccb);
569 if (ccb->ccb_h.status != CAM_REQ_CMP)
570 printf("cam_scan_callback: failure status = %x\n",
571 ccb->ccb_h.status);
572 else
573 twa_dbg_print(3, "success");
574
575 xpt_free_path(ccb->ccb_h.path);
576 free(ccb, M_TEMP);
577 }
578
579
580
581 /*
582 * Function name: twa_scsi_complete
583 * Description: Called to complete CAM scsi requests.
584 *
585 * Input: tr -- ptr to request pkt to be completed
586 * Output: None
587 * Return value: None
588 */
589 void
590 twa_scsi_complete(struct twa_request *tr)
591 {
592 struct twa_softc *sc = tr->tr_sc;
593 struct twa_command_header *cmd_hdr = &(tr->tr_command->cmd_hdr);
594 struct twa_command_9k *cmd = &(tr->tr_command->command.cmd_pkt_9k);
595 union ccb *ccb = (union ccb *)(tr->tr_private);
596 u_int16_t error;
597 u_int8_t *cdb;
598
599 twa_unset_timer(tr);
600
601 if (tr->tr_error) {
602 if (tr->tr_error == EBUSY)
603 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
604 else if (tr->tr_error == EFBIG)
605 ccb->ccb_h.status = CAM_REQ_TOO_BIG;
606 else
607 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
608 } else {
609 if (cmd->status) {
610 twa_dbg_dprint(1, sc, "req_id = 0x%x, status = 0x%x",
611 cmd->request_id,
612 cmd->status);
613
614 error = cmd_hdr->status_block.error;
615 if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
616 (error == TWA_ERROR_UNIT_OFFLINE)) {
617 twa_dbg_dprint(3, sc, "Unsupported unit. PTL = %x %x %x",
618 ccb->ccb_h.path_id,
619 ccb->ccb_h.target_id,
620 ccb->ccb_h.target_lun);
621 ccb->ccb_h.status |= CAM_TID_INVALID;
622 } else {
623 twa_dbg_dprint(2, sc, "cmd = %x %x %x %x %x %x %x",
624 cmd->command.opcode,
625 cmd->command.reserved,
626 cmd->unit,
627 cmd->request_id,
628 cmd->status,
629 cmd->sgl_offset,
630 cmd->sgl_entries);
631
632 cdb = (u_int8_t *)(cmd->cdb);
633 twa_dbg_dprint(2, sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
634 cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
635 cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
636
637 /*
638 * Print the error. Firmware doesn't yet support
639 * the 'Mode Sense' cmd. Don't print if the cmd
640 * is 'Mode Sense', and the error is 'Invalid field
641 * in CDB'.
642 */
643 if (! ((cdb[0] == 0x1A) && (error == 0x10D))) {
644 u_int8_t *error_str =
645 &(cmd_hdr->err_desc[strlen(cmd_hdr->err_desc) + 1]);
646
647 if (error_str[0] == '\0')
648 error_str =
649 twa_find_msg_string(twa_error_table, error);
650
651 twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
652 cdb[0],
653 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
654 error,
655 error_str,
656 cmd_hdr->err_desc);
657 }
658 }
659
660 bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
661 TWA_SENSE_DATA_LENGTH);
662 ccb->csio.sense_len = TWA_SENSE_DATA_LENGTH;
663 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
664 } else
665 ccb->ccb_h.status = CAM_REQ_CMP;
666
667 ccb->csio.scsi_status = cmd->status;
668 /* If simq is frozen, unfreeze it. */
669 if (sc->twa_state & TWA_STATE_SIMQ_FROZEN)
670 twa_allow_new_requests(sc, (void *)ccb);
671 }
672
673 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
674 xpt_done(ccb);
675 }
676
677
678
679 /*
680 * Function name: twa_drain_busy_queue
681 * Description: This function gets called after a controller reset.
682 * It errors back to CAM, all those requests that were
683 * pending with the firmware, at the time of the reset.
684 *
685 * Input: sc -- ptr to per ctlr structure
686 * Output: None
687 * Return value: None
688 */
689 void
690 twa_drain_busy_queue(struct twa_softc *sc)
691 {
692 struct twa_request *tr;
693 union ccb *ccb;
694
695 /* Walk the busy queue. */
696 while ((tr = twa_dequeue_busy(sc))) {
697 twa_unmap_request(tr);
698 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
699 (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
700 /*
701 * It's an internal/ioctl request. The callback/
702 * originator should do the clean-up (except unmapping).
703 */
704 tr->tr_error = EIO;
705 if (tr->tr_flags & TWA_CMD_SLEEP_ON_REQUEST) {
706 tr->tr_flags &= ~TWA_CMD_SLEEP_ON_REQUEST;
707 wakeup_one(tr);/* let the caller know */
708 }
709 else
710 if (tr->tr_callback)
711 tr->tr_callback(tr);
712 } else {
713 if ((ccb = tr->tr_private)) {
714 twa_unset_timer(tr);
715 /* It's a SCSI request. Complete it. */
716 ccb->ccb_h.status = CAM_SCSI_BUS_RESET;
717 twa_allow_new_requests(sc, ccb);
718 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
719 xpt_done(ccb);
720 }
721 twa_release_request(tr);
722 }
723 }
724 }
725
726
727
728 /*
729 * Function name: twa_allow_new_requests
730 * Description: Sets the appropriate status bits in a ccb such that,
731 * when the ccb is completed by a call to xpt_done,
732 * CAM knows that it's ok to unfreeze the flow of new
733 * requests to this controller, if the flow is frozen.
734 *
735 * Input: sc -- ptr to per ctlr structure
736 * ccb -- ptr to CAM request
737 * Output: None
738 * Return value: None
739 */
740 void
741 twa_allow_new_requests(struct twa_softc *sc, void *ccb)
742 {
743 ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
744 sc->twa_state &= ~TWA_STATE_SIMQ_FROZEN;
745 }
746
747
748
749 /*
750 * Function name: twa_disallow_new_requests
751 * Description: Calls the appropriate CAM function, so as to freeze
752 * the flow of new requests from CAM to this controller.
753 *
754 * Input: sc -- ptr to per ctlr structure
755 * Output: None
756 * Return value: None
757 */
758 void
759 twa_disallow_new_requests(struct twa_softc *sc)
760 {
761 xpt_freeze_simq(sc->twa_sim, 1);
762 sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
763 }
764
765
766
767 /*
768 * Function name: twa_set_timer
769 * Description: Set a timer to time a given request.
770 *
771 * Input: tr -- ptr to request pkt
772 * Output: None
773 * Return value: None
774 */
775 void
776 twa_set_timer(struct twa_request *tr)
777 {
778 union ccb *ccb = (union ccb *)(tr->tr_private);
779
780 /* Set the timer only if external (CAM) request. */
781 if (ccb) {
782 tr->tr_flags |= TWA_CMD_TIMER_SET;
783 ccb->ccb_h.timeout_ch = timeout(twa_timeout, tr,
784 (ccb->ccb_h.timeout * hz) / 1000);
785 }
786 }
787
788
789
790 /*
791 * Function name: twa_unset_timer
792 * Description: Unset a previously set timer.
793 *
794 * Input: tr -- ptr to request pkt
795 * Output: None
796 * Return value: None
797 */
798 void
799 twa_unset_timer(struct twa_request *tr)
800 {
801 union ccb *ccb = (union ccb *)(tr->tr_private);
802
803 if (tr->tr_flags & TWA_CMD_TIMER_SET) {
804 untimeout(twa_timeout, tr, ccb->ccb_h.timeout_ch);
805 tr->tr_flags &= ~TWA_CMD_TIMER_SET;
806 }
807 }
Cache object: 1e87aae412119d8910c2d0dc009c8525
|