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: releng/5.3/sys/dev/twa/twa_cam.c 129344 2004-05-17 17:16:58Z vkashyap $
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_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
54
55
56
57 /*
58 * Function name: twa_cam_setup
59 * Description: Attaches the driver to CAM.
60 *
61 * Input: sc -- ptr to per ctlr structure
62 * Output: None
63 * Return value: 0 -- success
64 * non-zero-- failure
65 */
66 int
67 twa_cam_setup(struct twa_softc *sc)
68 {
69 struct cam_devq *devq;
70 struct ccb_setasync csa;
71
72 twa_dbg_dprint(3, sc, "sc = %p", sc);
73 /*
74 * Create the device queue for our SIM.
75 */
76 devq = cam_simq_alloc(TWA_Q_LENGTH);
77 if (devq == NULL)
78 return(ENOMEM);
79
80 /*
81 * Create a SIM entry. Though we can support TWA_Q_LENGTH simultaneous
82 * requests, we claim to be able to handle only (TWA_Q_LENGTH - 1), so
83 * that we always have a request packet available to service attention
84 * interrupts.
85 */
86 twa_dbg_dprint(3, sc, "Calling cam_sim_alloc");
87 sc->twa_sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
88 device_get_unit(sc->twa_bus_dev),
89 TWA_Q_LENGTH - 1, 1, devq);
90 if (sc->twa_sim == NULL) {
91 cam_simq_free(devq);
92 return(ENOMEM);
93 }
94
95 /*
96 * Register the bus.
97 */
98 twa_dbg_dprint(3, sc, "Calling xpt_bus_register");
99 if (xpt_bus_register(sc->twa_sim, 0) != CAM_SUCCESS) {
100 cam_sim_free(sc->twa_sim, TRUE);
101 sc->twa_sim = NULL; /* so twa_cam_detach will not try to free it */
102 return(ENXIO);
103 }
104
105 twa_dbg_dprint(3, sc, "Calling xpt_create_path");
106 if (xpt_create_path(&sc->twa_path, NULL,
107 cam_sim_path(sc->twa_sim),
108 CAM_TARGET_WILDCARD,
109 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
110 xpt_bus_deregister(cam_sim_path (sc->twa_sim));
111 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
112 return(ENXIO);
113 }
114
115 twa_dbg_dprint(3, sc, "Calling xpt_setup_ccb");
116 xpt_setup_ccb(&csa.ccb_h, sc->twa_path, 5);
117 csa.ccb_h.func_code = XPT_SASYNC_CB;
118 csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
119 csa.callback = twa_async;
120 csa.callback_arg = sc;
121 xpt_action((union ccb *)&csa);
122
123 twa_dbg_dprint(3, sc, "Calling twa_request_bus_scan");
124 /*
125 * Request a bus scan, so that CAM gets to know of
126 * the logical units that we control.
127 */
128 twa_request_bus_scan(sc);
129 twa_dbg_dprint(3, sc, "Exiting");
130 return(0);
131 }
132
133
134
135 /*
136 * Function name: twa_cam_detach
137 * Description: Detaches the driver from CAM.
138 *
139 * Input: sc -- ptr to per ctlr structure
140 * Output: None
141 * Return value: None
142 */
143 void
144 twa_cam_detach(struct twa_softc *sc)
145 {
146 if (sc->twa_path)
147 xpt_free_path(sc->twa_path);
148 if (sc->twa_sim) {
149 xpt_bus_deregister(cam_sim_path(sc->twa_sim));
150 cam_sim_free(sc->twa_sim, TRUE); /* passing TRUE will free the devq as well */
151 }
152 }
153
154
155
156 /*
157 * Function name: twa_send_scsi_cmd
158 * Description: Sends down a scsi cmd to fw.
159 *
160 * Input: tr -- ptr to request pkt
161 * cmd -- opcode of scsi cmd to send
162 * Output: None
163 * Return value: 0 -- success
164 * non-zero-- failure
165 */
166 int
167 twa_send_scsi_cmd(struct twa_request *tr, int cmd)
168 {
169 union ccb ccb;
170
171 bzero(&ccb, sizeof(union ccb));
172 ccb.csio.cdb_io.cdb_bytes[0] = (u_int8_t)cmd;
173 ccb.csio.cdb_io.cdb_bytes[4] = 128;
174 ccb.csio.cdb_len = 16;
175 if ((ccb.csio.data_ptr = malloc(TWA_SECTOR_SIZE, M_DEVBUF, M_NOWAIT))
176 == NULL)
177 return(ENOMEM);
178 bzero(ccb.csio.data_ptr, TWA_SECTOR_SIZE);
179 ccb.csio.dxfer_len = TWA_SECTOR_SIZE;
180
181 ccb.ccb_h.target_id = 0;
182 ccb.ccb_h.flags |= CAM_DIR_IN;
183
184 if (twa_execute_scsi(tr, &ccb))
185 return(EIO);
186 return(0);
187 }
188
189
190
191 /*
192 * Function name: twa_execute_scsi
193 * Description: Build a fw cmd, based on a CAM style ccb, and
194 * send it down.
195 *
196 * Input: tr -- ptr to request pkt
197 * ccb -- ptr to CAM style ccb
198 * Output: None
199 * Return value: 0 -- success
200 * non-zero-- failure
201 */
202 int
203 twa_execute_scsi(struct twa_request *tr, union ccb *ccb)
204 {
205 struct twa_softc *sc = tr->tr_sc;
206 struct twa_command_packet *cmdpkt;
207 struct twa_command_9k *cmd9k;
208 struct ccb_hdr *ccb_h = &(ccb->ccb_h);
209 struct ccb_scsiio *csio = &(ccb->csio);
210 int error;
211
212 twa_dbg_dprint(3, sc, "SCSI I/O request 0x%x",
213 csio->cdb_io.cdb_bytes[0]);
214
215 if (ccb_h->target_id >= TWA_MAX_UNITS) {
216 twa_dbg_dprint(3, sc, "Invalid target. PTL = %x %x %x",
217 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
218 ccb_h->status |= CAM_TID_INVALID;
219 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
220 xpt_done(ccb);
221 return(1);
222 }
223 if (ccb_h->target_lun != 0) {
224 twa_dbg_dprint(3, sc, "Invalid lun. PTL = %x %x %x",
225 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
226 ccb_h->status |= CAM_LUN_INVALID;
227 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
228 xpt_done(ccb);
229 return(1);
230 }
231
232 if(ccb_h->flags & CAM_CDB_PHYS) {
233 twa_printf(sc, "Physical CDB address!\n");
234 ccb_h->status = CAM_REQ_CMP_ERR;
235 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
236 xpt_done(ccb);
237 return(1);
238 }
239
240 /*
241 * We are going to work on this request. Mark it as enqueued (though
242 * we don't actually queue it...)
243 */
244 ccb_h->status |= CAM_SIM_QUEUED;
245
246 if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
247 if(ccb_h->flags & CAM_DIR_IN)
248 tr->tr_flags |= TWA_CMD_DATA_IN;
249 else
250 tr->tr_flags |= TWA_CMD_DATA_OUT;
251 }
252
253 cmdpkt = tr->tr_command;
254
255 cmdpkt->cmd_hdr.header_desc.size_header = 128;
256
257 cmd9k = &(cmdpkt->command.cmd_pkt_9k);
258 cmd9k->command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND;
259 cmd9k->unit = ccb_h->target_id;
260 cmd9k->request_id = tr->tr_request_id;
261 cmd9k->status = 0;
262 cmd9k->sgl_offset = 16; /* offset from end of hdr = max cdb len */
263
264 if(ccb_h->flags & CAM_CDB_POINTER)
265 bcopy(csio->cdb_io.cdb_ptr, cmd9k->cdb, csio->cdb_len);
266 else
267 bcopy(csio->cdb_io.cdb_bytes, cmd9k->cdb, csio->cdb_len);
268
269 if (!(ccb_h->flags & CAM_DATA_PHYS)) {
270 /* Virtual data addresses. Need to convert them... */
271 twa_dbg_dprint(3, sc, "XPT_SCSI_IO: Single virtual address!");
272 if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
273 if (csio->dxfer_len > TWA_MAX_IO_SIZE) {
274 twa_printf(sc, "I/O size %d too big.\n",
275 csio->dxfer_len);
276 ccb_h->status = CAM_REQ_TOO_BIG;
277 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL)
278 xpt_done(ccb);
279 return(1);
280 }
281
282 if ((tr->tr_length = csio->dxfer_len)) {
283 tr->tr_data = csio->data_ptr;
284 cmd9k->sgl_entries = 1;
285 }
286 } else {
287 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
288 ccb_h->status = CAM_REQ_CMP_ERR;
289 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
290 xpt_done(ccb);
291 }
292 return(1);
293 }
294 } else {
295 /* Data addresses are physical. */
296 twa_printf(sc, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
297 ccb_h->status = CAM_REQ_CMP_ERR;
298 if (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_EXTERNAL) {
299 ccb_h->status |= CAM_RELEASE_SIMQ;
300 ccb_h->status &= ~CAM_SIM_QUEUED;
301 xpt_done(ccb);
302 }
303 return(1);
304 }
305
306 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_9K;
307 /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
308 error = twa_map_request(tr);
309 return(error);
310 }
311
312
313
314 /*
315 * Function name: twa_action
316 * Description: Driver entry point for CAM's use.
317 *
318 * Input: sim -- sim corresponding to the ctlr
319 * ccb -- ptr to CAM request
320 * Output: None
321 * Return value: None
322 */
323 void
324 twa_action(struct cam_sim *sim, union ccb *ccb)
325 {
326 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
327 struct ccb_hdr *ccb_h = &(ccb->ccb_h);
328
329 switch (ccb_h->func_code) {
330 case XPT_SCSI_IO: /* SCSI I/O */
331 {
332 struct twa_request *tr;
333
334 if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
335 ((tr = twa_get_request(sc)) == NULL)) {
336 twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
337 /*
338 * Freeze the simq to maintain ccb ordering. The next
339 * ccb that gets completed will unfreeze the simq.
340 */
341 twa_disallow_new_requests(sc);
342 ccb_h->status |= CAM_REQUEUE_REQ;
343 xpt_done(ccb);
344 break;
345 }
346 tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
347 tr->tr_private = ccb;
348 tr->tr_callback = twa_complete_io;
349 if (twa_execute_scsi(tr, ccb))
350 twa_release_request(tr);
351 break;
352 }
353
354 case XPT_ABORT:
355 twa_dbg_dprint(2, sc, "Abort request");
356 ccb_h->status = CAM_UA_ABORT;
357 xpt_done(ccb);
358 break;
359
360 case XPT_RESET_BUS:
361 twa_printf(sc, "Reset Bus request from CAM...\n");
362 if (twa_reset(sc)) {
363 twa_printf(sc, "Reset Bus failed!\n");
364 ccb_h->status = CAM_REQ_CMP_ERR;
365 }
366 else
367 ccb_h->status = CAM_REQ_CMP;
368
369 xpt_done(ccb);
370 break;
371
372 case XPT_SET_TRAN_SETTINGS:
373 twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS");
374
375 /*
376 * This command is not supported, since it's very specific
377 * to SCSI, and we are doing ATA.
378 */
379 ccb_h->status = CAM_FUNC_NOTAVAIL;
380 xpt_done(ccb);
381 break;
382
383 case XPT_GET_TRAN_SETTINGS:
384 {
385 struct ccb_trans_settings *cts = &ccb->cts;
386
387 twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
388 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
389 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
390 ccb_h->status = CAM_REQ_CMP;
391 xpt_done(ccb);
392 break;
393 }
394
395 case XPT_CALC_GEOMETRY:
396 twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
397 cam_calc_geometry(&ccb->ccg, 1/* extended */);
398 xpt_done(ccb);
399 break;
400
401 case XPT_PATH_INQ: /* Path inquiry -- get twa properties */
402 {
403 struct ccb_pathinq *path_inq = &ccb->cpi;
404
405 twa_dbg_dprint(3, sc, "XPT_PATH_INQ request");
406
407 path_inq->version_num = 1;
408 path_inq->hba_inquiry = 0;
409 path_inq->target_sprt = 0;
410 path_inq->hba_misc = 0;
411 path_inq->hba_eng_cnt = 0;
412 path_inq->max_target = TWA_MAX_UNITS;
413 path_inq->max_lun = 0;
414 path_inq->unit_number = cam_sim_unit(sim);
415 path_inq->bus_id = cam_sim_bus(sim);
416 path_inq->initiator_id = 12;
417 path_inq->base_transfer_speed = 100000;
418 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
419 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
420 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
421 ccb_h->status = CAM_REQ_CMP;
422 xpt_done(ccb);
423 break;
424 }
425
426 default:
427 twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
428 ccb_h->status = CAM_REQ_INVALID;
429 xpt_done(ccb);
430 break;
431 }
432 }
433
434
435
436 /*
437 * Function name: twa_poll
438 * Description: Driver entry point called when interrupts are not available.
439 *
440 * Input: sim -- sim corresponding to the controller
441 * Output: None
442 * Return value: None
443 */
444 void
445 twa_poll(struct cam_sim *sim)
446 {
447 #ifdef TWA_DEBUG
448 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
449 #endif /* TWA_DEBUG */
450
451 twa_dbg_dprint(3, sc, "Entering sc = %p", sc);
452 twa_interrupt(cam_sim_softc(sim));
453 twa_dbg_dprint(3, sc, "Exiting sc = %p", sc);
454 }
455
456
457
458 /*
459 * Function name: twa_async
460 * Description: Driver entry point for CAM to notify driver of special
461 * events. We don't use this for now.
462 *
463 * Input: callback_arg -- ptr to per ctlr structure
464 * code -- code associated with the event
465 * path -- cam path
466 * arg --
467 * Output: None
468 * Return value: 0 -- success
469 * non-zero-- failure
470 */
471 void
472 twa_async(void *callback_arg, u_int32_t code,
473 struct cam_path *path, void *arg)
474 {
475 #ifdef TWA_DEBUG
476 struct twa_softc *sc = (struct twa_softc *)callback_arg;
477 #endif /* TWA_DEBUG */
478
479 twa_dbg_dprint(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
480 sc, code, path, arg);
481 }
482
483
484
485 /*
486 * Function name: twa_request_bus_scan
487 * Description: Requests CAM for a scan of the bus.
488 *
489 * Input: sc -- ptr to per ctlr structure
490 * Output: None
491 * Return value: None
492 */
493 void
494 twa_request_bus_scan(struct twa_softc *sc)
495 {
496 struct cam_path *path;
497 union ccb *ccb;
498
499 if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
500 return;
501 bzero(ccb, sizeof(union ccb));
502 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->twa_sim),
503 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
504 return;
505
506 xpt_setup_ccb(&ccb->ccb_h, path, 5);
507 ccb->ccb_h.func_code = XPT_SCAN_BUS;
508 ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
509 ccb->crcn.flags = CAM_FLAG_NONE;
510 xpt_action(ccb);
511 }
512
513
514
515 /*
516 * Function name: twa_bus_scan_cb
517 * Description: Callback from CAM on a bus scan request.
518 *
519 * Input: periph -- we don't use this
520 * ccb -- bus scan request ccb that we sent to CAM
521 * Output: None
522 * Return value: None
523 */
524 static void
525 twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
526 {
527 twa_dbg_print(3, "ccb = %p\n", ccb);
528 if (ccb->ccb_h.status != CAM_REQ_CMP)
529 printf("cam_scan_callback: failure status = %x\n",
530 ccb->ccb_h.status);
531 else
532 twa_dbg_print(3, "success");
533
534 xpt_free_path(ccb->ccb_h.path);
535 free(ccb, M_TEMP);
536 }
537
538
539
540 /*
541 * Function name: twa_scsi_complete
542 * Description: Called to complete CAM scsi requests.
543 *
544 * Input: tr -- ptr to request pkt to be completed
545 * Output: None
546 * Return value: None
547 */
548 void
549 twa_scsi_complete(struct twa_request *tr)
550 {
551 struct twa_softc *sc = tr->tr_sc;
552 struct twa_command_header *cmd_hdr = &(tr->tr_command->cmd_hdr);
553 struct twa_command_9k *cmd = &(tr->tr_command->command.cmd_pkt_9k);
554 union ccb *ccb = (union ccb *)(tr->tr_private);
555 u_int16_t error;
556 u_int8_t *cdb;
557
558 if (tr->tr_error) {
559 if (tr->tr_error == EBUSY)
560 ccb->ccb_h.status |= CAM_REQUEUE_REQ;
561 else if (tr->tr_error == EFBIG)
562 ccb->ccb_h.status = CAM_REQ_TOO_BIG;
563 else
564 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
565 } else {
566 if (cmd->status) {
567 twa_dbg_dprint(1, sc, "req_id = 0x%x, status = 0x%x",
568 cmd->request_id,
569 cmd->status);
570
571 error = cmd_hdr->status_block.error;
572 if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
573 (error == TWA_ERROR_UNIT_OFFLINE)) {
574 twa_dbg_dprint(3, sc, "Unsupported unit. PTL = %x %x %x",
575 ccb->ccb_h.path_id,
576 ccb->ccb_h.target_id,
577 ccb->ccb_h.target_lun);
578 ccb->ccb_h.status |= CAM_TID_INVALID;
579 } else {
580 twa_dbg_dprint(2, sc, "cmd = %x %x %x %x %x %x %x",
581 cmd->command.opcode,
582 cmd->command.reserved,
583 cmd->unit,
584 cmd->request_id,
585 cmd->status,
586 cmd->sgl_offset,
587 cmd->sgl_entries);
588
589 cdb = (u_int8_t *)(cmd->cdb);
590 twa_dbg_dprint(2, sc, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
591 cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7],
592 cdb[8], cdb[9], cdb[10], cdb[11], cdb[12], cdb[13], cdb[14], cdb[15]);
593
594 cmd_hdr->err_specific_desc[sizeof(cmd_hdr->err_specific_desc) - 1] = '\0';
595 /*
596 * Print the error. Firmware doesn't yet support
597 * the 'Mode Sense' cmd. Don't print if the cmd
598 * is 'Mode Sense', and the error is 'Invalid field
599 * in CDB'.
600 */
601 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
602 twa_printf(sc, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
603 cdb[0],
604 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR,
605 error,
606 twa_find_msg_string(twa_error_table, error),
607 cmd_hdr->err_specific_desc);
608 }
609
610 bcopy(cmd_hdr->sense_data, &(ccb->csio.sense_data),
611 TWA_SENSE_DATA_LENGTH);
612 ccb->csio.sense_len = TWA_SENSE_DATA_LENGTH;
613 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
614 } else
615 ccb->ccb_h.status = CAM_REQ_CMP;
616
617 ccb->csio.scsi_status = cmd->status;
618 /* If simq is frozen, unfreeze it. */
619 if (sc->twa_state & TWA_STATE_SIMQ_FROZEN)
620 twa_allow_new_requests(sc, (void *)ccb);
621 }
622
623 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
624 xpt_done(ccb);
625 }
626
627
628
629 /*
630 * Function name: twa_drain_busy_queue
631 * Description: This function gets called after a controller reset.
632 * It errors back to CAM, all those requests that were
633 * pending with the firmware, at the time of the reset.
634 *
635 * Input: sc -- ptr to per ctlr structure
636 * Output: None
637 * Return value: None
638 */
639 void
640 twa_drain_busy_queue(struct twa_softc *sc)
641 {
642 struct twa_request *tr;
643 union ccb *ccb;
644
645 /* Walk the busy queue. */
646 while ((tr = twa_dequeue_busy(sc))) {
647 twa_unmap_request(tr);
648 if ((tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_INTERNAL) ||
649 (tr->tr_cmd_pkt_type & TWA_CMD_PKT_TYPE_IOCTL)) {
650 /* It's an internal/ioctl request. Simply free it. */
651 if (tr->tr_data)
652 free(tr->tr_data, M_DEVBUF);
653 } else {
654 if ((ccb = tr->tr_private)) {
655 /* It's a SCSI request. Complete it. */
656 ccb->ccb_h.status = CAM_SCSI_BUS_RESET |
657 CAM_RELEASE_SIMQ;
658 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
659 xpt_done(ccb);
660 }
661 }
662 twa_release_request(tr);
663 }
664 }
665
666
667
668 /*
669 * Function name: twa_allow_new_requests
670 * Description: Sets the appropriate status bits in a ccb such that,
671 * when the ccb is completed by a call to xpt_done,
672 * CAM knows that it's ok to unfreeze the flow of new
673 * requests to this controller, if the flow is frozen.
674 *
675 * Input: sc -- ptr to per ctlr structure
676 * ccb -- ptr to CAM request
677 * Output: None
678 * Return value: None
679 */
680 void
681 twa_allow_new_requests(struct twa_softc *sc, void *ccb)
682 {
683 ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
684 sc->twa_state &= ~TWA_STATE_SIMQ_FROZEN;
685 }
686
687
688
689 /*
690 * Function name: twa_disallow_new_requests
691 * Description: Calls the appropriate CAM function, so as to freeze
692 * the flow of new requests from CAM to this controller.
693 *
694 * Input: sc -- ptr to per ctlr structure
695 * Output: None
696 * Return value: None
697 */
698 void
699 twa_disallow_new_requests(struct twa_softc *sc)
700 {
701 xpt_freeze_simq(sc->twa_sim, 1);
702 sc->twa_state |= TWA_STATE_SIMQ_FROZEN;
703 }
Cache object: a3b55a89adb4012681706f7c75c3875a
|