2 * Copyright (c) 2003-04 3ware, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 * $DragonFly: src/sys/dev/raid/twa/twa_cam.c,v 1.10 2008/05/18 20:30:23 pavalos Exp $
31 * 3ware driver for 9000 series storage controllers.
33 * Author: Vinod Kashyap
37 #include "twa_includes.h"
39 #include <bus/cam/cam.h>
40 #include <bus/cam/cam_ccb.h>
41 #include <bus/cam/cam_sim.h>
42 #include <bus/cam/cam_xpt_sim.h>
43 #include <bus/cam/cam_xpt_periph.h>
44 #include <bus/cam/cam_debug.h>
45 #include <bus/cam/cam_periph.h>
47 #include <bus/cam/scsi/scsi_all.h>
48 #include <bus/cam/scsi/scsi_message.h>
50 static int twa_execute_scsi(struct twa_request
*tr
, union ccb
*ccb
);
51 static void twa_action(struct cam_sim
*sim
, union ccb
*ccb
);
52 static void twa_poll(struct cam_sim
*sim
);
53 static void twa_async(void *callback_arg
, u_int32_t code
, struct cam_path
*path
, void *arg
);
54 static void twa_bus_scan_cb(struct cam_periph
*periph
, union ccb
*ccb
);
59 * Function name: twa_cam_setup
60 * Description: Attaches the driver to CAM.
62 * Input: sc -- ptr to per ctlr structure
64 * Return value: 0 -- success
68 twa_cam_setup(struct twa_softc
*sc
)
70 struct cam_devq
*devq
;
71 struct ccb_setasync csa
;
73 twa_dbg_dprint(3, sc
, "sc = %p", sc
);
75 * Create the device queue for our SIM.
77 devq
= cam_simq_alloc(TWA_Q_LENGTH
);
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
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
),
91 TWA_Q_LENGTH
- 1, 1, devq
);
92 cam_simq_release(devq
);
93 if (sc
->twa_sim
== NULL
) {
100 twa_dbg_dprint(3, sc
, "Calling xpt_bus_register");
101 if (xpt_bus_register(sc
->twa_sim
, 0) != CAM_SUCCESS
) {
102 cam_sim_free(sc
->twa_sim
);
103 sc
->twa_sim
= NULL
; /* so twa_cam_detach will not try to free it */
107 twa_dbg_dprint(3, sc
, "Calling xpt_create_path");
108 if (xpt_create_path(&sc
->twa_path
, NULL
,
109 cam_sim_path(sc
->twa_sim
),
111 CAM_LUN_WILDCARD
) != CAM_REQ_CMP
) {
112 xpt_bus_deregister(cam_sim_path (sc
->twa_sim
));
113 cam_sim_free(sc
->twa_sim
); /* passing TRUE will free the devq as well */
117 twa_dbg_dprint(3, sc
, "Calling xpt_setup_ccb");
118 xpt_setup_ccb(&csa
.ccb_h
, sc
->twa_path
, 5);
119 csa
.ccb_h
.func_code
= XPT_SASYNC_CB
;
120 csa
.event_enable
= AC_FOUND_DEVICE
| AC_LOST_DEVICE
;
121 csa
.callback
= twa_async
;
122 csa
.callback_arg
= sc
;
123 xpt_action((union ccb
*)&csa
);
125 twa_dbg_dprint(3, sc
, "Calling twa_request_bus_scan");
127 * Request a bus scan, so that CAM gets to know of
128 * the logical units that we control.
130 twa_request_bus_scan(sc
);
131 twa_dbg_dprint(3, sc
, "Exiting");
138 * Function name: twa_cam_detach
139 * Description: Detaches the driver from CAM.
141 * Input: sc -- ptr to per ctlr structure
146 twa_cam_detach(struct twa_softc
*sc
)
149 xpt_free_path(sc
->twa_path
);
151 xpt_bus_deregister(cam_sim_path(sc
->twa_sim
));
152 cam_sim_free(sc
->twa_sim
); /* passing TRUE will free the devq as well */
159 * Function name: twa_send_scsi_cmd
160 * Description: Sends down a scsi cmd to fw.
162 * Input: tr -- ptr to request pkt
163 * cmd -- opcode of scsi cmd to send
165 * Return value: 0 -- success
169 twa_send_scsi_cmd(struct twa_request
*tr
, int cmd
)
173 bzero(&ccb
, sizeof(union ccb
));
174 ccb
.csio
.cdb_io
.cdb_bytes
[0] = (u_int8_t
)cmd
;
175 ccb
.csio
.cdb_io
.cdb_bytes
[4] = 128;
176 ccb
.csio
.cdb_len
= 16;
177 ccb
.csio
.data_ptr
= kmalloc(TWA_SECTOR_SIZE
, M_DEVBUF
, M_INTWAIT
|M_ZERO
);
178 ccb
.csio
.dxfer_len
= TWA_SECTOR_SIZE
;
180 ccb
.ccb_h
.target_id
= 0;
181 ccb
.ccb_h
.flags
|= CAM_DIR_IN
;
183 if (twa_execute_scsi(tr
, &ccb
))
191 * Function name: twa_execute_scsi
192 * Description: Build a fw cmd, based on a CAM style ccb, and
195 * Input: tr -- ptr to request pkt
196 * ccb -- ptr to CAM style ccb
198 * Return value: 0 -- success
202 twa_execute_scsi(struct twa_request
*tr
, union ccb
*ccb
)
204 struct twa_softc
*sc
= tr
->tr_sc
;
205 struct twa_command_packet
*cmdpkt
;
206 struct twa_command_9k
*cmd9k
;
207 struct ccb_hdr
*ccb_h
= &(ccb
->ccb_h
);
208 struct ccb_scsiio
*csio
= &(ccb
->csio
);
211 twa_dbg_dprint(3, sc
, "SCSI I/O request 0x%x",
212 csio
->cdb_io
.cdb_bytes
[0]);
214 if (ccb_h
->target_id
>= TWA_MAX_UNITS
) {
215 twa_dbg_dprint(3, sc
, "Invalid target. PTL = %x %x %x",
216 ccb_h
->path_id
, ccb_h
->target_id
, ccb_h
->target_lun
);
217 ccb_h
->status
|= CAM_TID_INVALID
;
218 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
)
222 if (ccb_h
->target_lun
!= 0) {
223 twa_dbg_dprint(3, sc
, "Invalid lun. PTL = %x %x %x",
224 ccb_h
->path_id
, ccb_h
->target_id
, ccb_h
->target_lun
);
225 ccb_h
->status
|= CAM_LUN_INVALID
;
226 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
)
231 if(ccb_h
->flags
& CAM_CDB_PHYS
) {
232 twa_printf(sc
, "Physical CDB address!\n");
233 ccb_h
->status
= CAM_REQ_CMP_ERR
;
234 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
)
240 * We are going to work on this request. Mark it as enqueued (though
241 * we don't actually queue it...)
243 ccb_h
->status
|= CAM_SIM_QUEUED
;
245 if((ccb_h
->flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
) {
246 if(ccb_h
->flags
& CAM_DIR_IN
)
247 tr
->tr_flags
|= TWA_CMD_DATA_IN
;
249 tr
->tr_flags
|= TWA_CMD_DATA_OUT
;
252 cmdpkt
= tr
->tr_command
;
254 cmdpkt
->cmd_hdr
.header_desc
.size_header
= 128;
256 cmd9k
= &(cmdpkt
->command
.cmd_pkt_9k
);
257 cmd9k
->command
.opcode
= TWA_OP_EXECUTE_SCSI_COMMAND
;
258 cmd9k
->unit
= ccb_h
->target_id
;
259 cmd9k
->request_id
= tr
->tr_request_id
;
261 cmd9k
->sgl_offset
= 16; /* offset from end of hdr = max cdb len */
263 if(ccb_h
->flags
& CAM_CDB_POINTER
)
264 bcopy(csio
->cdb_io
.cdb_ptr
, cmd9k
->cdb
, csio
->cdb_len
);
266 bcopy(csio
->cdb_io
.cdb_bytes
, cmd9k
->cdb
, csio
->cdb_len
);
268 if (!(ccb_h
->flags
& CAM_DATA_PHYS
)) {
269 /* Virtual data addresses. Need to convert them... */
270 twa_dbg_dprint(3, sc
, "XPT_SCSI_IO: Single virtual address!");
271 if (!(ccb_h
->flags
& CAM_SCATTER_VALID
)) {
272 if (csio
->dxfer_len
> TWA_MAX_IO_SIZE
) {
273 twa_printf(sc
, "I/O size %d too big.\n",
275 ccb_h
->status
= CAM_REQ_TOO_BIG
;
276 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
)
281 if ((tr
->tr_length
= csio
->dxfer_len
)) {
282 tr
->tr_data
= csio
->data_ptr
;
283 cmd9k
->sgl_entries
= 1;
286 twa_printf(sc
, "twa_execute_scsi: XPT_SCSI_IO: Got SGList!\n");
287 ccb_h
->status
= CAM_REQ_CMP_ERR
;
288 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
) {
294 /* Data addresses are physical. */
295 twa_printf(sc
, "twa_execute_scsi: XPT_SCSI_IO: Physical data addresses!\n");
296 ccb_h
->status
= CAM_REQ_CMP_ERR
;
297 if (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_EXTERNAL
) {
298 ccb_h
->status
|= CAM_RELEASE_SIMQ
;
299 ccb_h
->status
&= ~CAM_SIM_QUEUED
;
305 tr
->tr_cmd_pkt_type
|= TWA_CMD_PKT_TYPE_9K
;
306 /* twa_setup_data_dmamap will fill in the SGL, and submit the I/O. */
307 error
= twa_map_request(tr
);
314 * Function name: twa_action
315 * Description: Driver entry point for CAM's use.
317 * Input: sim -- sim corresponding to the ctlr
318 * ccb -- ptr to CAM request
323 twa_action(struct cam_sim
*sim
, union ccb
*ccb
)
325 struct twa_softc
*sc
= (struct twa_softc
*)cam_sim_softc(sim
);
326 struct ccb_hdr
*ccb_h
= &(ccb
->ccb_h
);
328 switch (ccb_h
->func_code
) {
329 case XPT_SCSI_IO
: /* SCSI I/O */
331 struct twa_request
*tr
;
333 if ((sc
->twa_state
& TWA_STATE_SIMQ_FROZEN
) ||
334 ((tr
= twa_get_request(sc
)) == NULL
)) {
335 twa_dbg_dprint(2, sc
, "simq frozen/Cannot get request pkt.");
337 * Freeze the simq to maintain ccb ordering. The next
338 * ccb that gets completed will unfreeze the simq.
340 twa_disallow_new_requests(sc
);
341 ccb_h
->status
|= CAM_REQUEUE_REQ
;
345 tr
->tr_cmd_pkt_type
|= TWA_CMD_PKT_TYPE_EXTERNAL
;
346 tr
->tr_private
= ccb
;
347 tr
->tr_callback
= twa_complete_io
;
348 if (twa_execute_scsi(tr
, ccb
))
349 twa_release_request(tr
);
354 twa_dbg_dprint(2, sc
, "Abort request");
355 ccb_h
->status
= CAM_UA_ABORT
;
360 twa_printf(sc
, "Reset Bus request from CAM...\n");
362 twa_printf(sc
, "Reset Bus failed!\n");
363 ccb_h
->status
= CAM_REQ_CMP_ERR
;
366 ccb_h
->status
= CAM_REQ_CMP
;
371 case XPT_SET_TRAN_SETTINGS
:
372 twa_dbg_dprint(3, sc
, "XPT_SET_TRAN_SETTINGS");
375 * This command is not supported, since it's very specific
376 * to SCSI, and we are doing ATA.
378 ccb_h
->status
= CAM_FUNC_NOTAVAIL
;
382 case XPT_GET_TRAN_SETTINGS
:
384 struct ccb_trans_settings
*cts
= &ccb
->cts
;
385 struct ccb_trans_settings_scsi
*scsi
=
386 &cts
->proto_specific
.scsi
;
387 struct ccb_trans_settings_spi
*spi
=
388 &cts
->xport_specific
.spi
;
390 cts
->protocol
= PROTO_SCSI
;
391 cts
->protocol_version
= SCSI_REV_2
;
392 cts
->transport
= XPORT_SPI
;
393 cts
->transport_version
= 2;
395 spi
->valid
= CTS_SPI_VALID_DISC
;
396 spi
->flags
= CTS_SPI_FLAGS_DISC_ENB
;
397 scsi
->valid
= CTS_SCSI_VALID_TQ
;
398 scsi
->flags
= CTS_SCSI_FLAGS_TAG_ENB
;
399 twa_dbg_dprint(3, sc
, "XPT_GET_TRAN_SETTINGS");
400 ccb_h
->status
= CAM_REQ_CMP
;
405 case XPT_CALC_GEOMETRY
:
407 struct ccb_calc_geometry
*geom
;
409 twa_dbg_dprint(3, sc
, "XPT_CALC_GEOMETRY request");
412 if (geom
->volume_size
> 0x200000) /* 1 GB */ {
414 geom
->secs_per_track
= 63;
417 geom
->secs_per_track
= 32;
419 geom
->cylinders
= geom
->volume_size
/
420 (geom
->heads
* geom
->secs_per_track
);
421 ccb_h
->status
= CAM_REQ_CMP
;
426 case XPT_PATH_INQ
: /* Path inquiry -- get twa properties */
428 struct ccb_pathinq
*path_inq
= &ccb
->cpi
;
430 twa_dbg_dprint(3, sc
, "XPT_PATH_INQ request");
432 path_inq
->version_num
= 1;
433 path_inq
->hba_inquiry
= 0;
434 path_inq
->target_sprt
= 0;
435 path_inq
->hba_misc
= 0;
436 path_inq
->hba_eng_cnt
= 0;
437 path_inq
->max_target
= TWA_MAX_UNITS
;
438 path_inq
->max_lun
= 0;
439 path_inq
->unit_number
= cam_sim_unit(sim
);
440 path_inq
->bus_id
= cam_sim_bus(sim
);
441 path_inq
->initiator_id
= 12;
442 path_inq
->base_transfer_speed
= 100000;
443 strncpy(path_inq
->sim_vid
, "FreeBSD", SIM_IDLEN
);
444 strncpy(path_inq
->hba_vid
, "3ware", HBA_IDLEN
);
445 strncpy(path_inq
->dev_name
, cam_sim_name(sim
), DEV_IDLEN
);
446 path_inq
->transport
= XPORT_SPI
;
447 path_inq
->transport_version
= 2;
448 path_inq
->protocol
= PROTO_SCSI
;
449 path_inq
->protocol_version
= SCSI_REV_2
;
450 ccb_h
->status
= CAM_REQ_CMP
;
456 twa_dbg_dprint(3, sc
, "func_code = %x", ccb_h
->func_code
);
457 ccb_h
->status
= CAM_REQ_INVALID
;
466 * Function name: twa_poll
467 * Description: Driver entry point called when interrupts are not available.
469 * Input: sim -- sim corresponding to the controller
474 twa_poll(struct cam_sim
*sim
)
477 struct twa_softc
*sc
= (struct twa_softc
*)cam_sim_softc(sim
);
478 #endif /* TWA_DEBUG */
480 twa_dbg_dprint(3, sc
, "Entering sc = %p", sc
);
481 twa_interrupt(cam_sim_softc(sim
));
482 twa_dbg_dprint(3, sc
, "Exiting sc = %p", sc
);
488 * Function name: twa_async
489 * Description: Driver entry point for CAM to notify driver of special
490 * events. We don't use this for now.
492 * Input: callback_arg -- ptr to per ctlr structure
493 * code -- code associated with the event
497 * Return value: 0 -- success
501 twa_async(void *callback_arg
, u_int32_t code
,
502 struct cam_path
*path
, void *arg
)
505 struct twa_softc
*sc
= (struct twa_softc
*)callback_arg
;
506 #endif /* TWA_DEBUG */
508 twa_dbg_dprint(3, sc
, "sc = %p, code = %x, path = %p, arg = %p",
509 sc
, code
, path
, arg
);
515 * Function name: twa_request_bus_scan
516 * Description: Requests CAM for a scan of the bus.
518 * Input: sc -- ptr to per ctlr structure
523 twa_request_bus_scan(struct twa_softc
*sc
)
525 struct cam_path
*path
;
528 ccb
= kmalloc(sizeof(union ccb
), M_TEMP
, M_WAITOK
| M_ZERO
);
529 if (xpt_create_path(&path
, xpt_periph
, cam_sim_path(sc
->twa_sim
),
530 CAM_TARGET_WILDCARD
, CAM_LUN_WILDCARD
) != CAM_REQ_CMP
)
533 xpt_setup_ccb(&ccb
->ccb_h
, path
, 5);
534 ccb
->ccb_h
.func_code
= XPT_SCAN_BUS
;
535 ccb
->ccb_h
.cbfcnp
= twa_bus_scan_cb
;
536 ccb
->crcn
.flags
= CAM_FLAG_NONE
;
543 * Function name: twa_bus_scan_cb
544 * Description: Callback from CAM on a bus scan request.
546 * Input: periph -- we don't use this
547 * ccb -- bus scan request ccb that we sent to CAM
552 twa_bus_scan_cb(struct cam_periph
*periph
, union ccb
*ccb
)
554 twa_dbg_print(3, "ccb = %p\n", ccb
);
555 if (ccb
->ccb_h
.status
!= CAM_REQ_CMP
)
556 kprintf("cam_scan_callback: failure status = %x\n",
559 twa_dbg_print(3, "success");
561 xpt_free_path(ccb
->ccb_h
.path
);
568 * Function name: twa_scsi_complete
569 * Description: Called to complete CAM scsi requests.
571 * Input: tr -- ptr to request pkt to be completed
576 twa_scsi_complete(struct twa_request
*tr
)
578 struct twa_softc
*sc
= tr
->tr_sc
;
579 struct twa_command_header
*cmd_hdr
= &(tr
->tr_command
->cmd_hdr
);
580 struct twa_command_9k
*cmd
= &(tr
->tr_command
->command
.cmd_pkt_9k
);
581 union ccb
*ccb
= (union ccb
*)(tr
->tr_private
);
586 if (tr
->tr_error
== EBUSY
)
587 ccb
->ccb_h
.status
|= CAM_REQUEUE_REQ
;
588 else if (tr
->tr_error
== EFBIG
)
589 ccb
->ccb_h
.status
= CAM_REQ_TOO_BIG
;
591 ccb
->ccb_h
.status
= CAM_REQ_CMP_ERR
;
594 twa_dbg_dprint(1, sc
, "req_id = 0x%x, status = 0x%x",
598 error
= cmd_hdr
->status_block
.error
;
599 if ((error
== TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED
) ||
600 (error
== TWA_ERROR_UNIT_OFFLINE
)) {
601 twa_dbg_dprint(3, sc
, "Unsupported unit. PTL = %x %x %x",
603 ccb
->ccb_h
.target_id
,
604 ccb
->ccb_h
.target_lun
);
605 ccb
->ccb_h
.status
|= CAM_TID_INVALID
;
607 twa_dbg_dprint(2, sc
, "cmd = %x %x %x %x %x %x %x",
609 cmd
->command
.reserved
,
616 cdb
= (u_int8_t
*)(cmd
->cdb
);
617 twa_dbg_dprint(2, sc
, "cdb = %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
618 cdb
[0], cdb
[1], cdb
[2], cdb
[3], cdb
[4], cdb
[5], cdb
[6], cdb
[7],
619 cdb
[8], cdb
[9], cdb
[10], cdb
[11], cdb
[12], cdb
[13], cdb
[14], cdb
[15]);
621 cmd_hdr
->err_specific_desc
[sizeof(cmd_hdr
->err_specific_desc
) - 1] = '\0';
623 * Print the error. Firmware doesn't yet support
624 * the 'Mode Sense' cmd. Don't print if the cmd
625 * is 'Mode Sense', and the error is 'Invalid field
628 if (! ((cdb
[0] == 0x1A) && (error
== 0x10D)))
629 twa_printf(sc
, "SCSI cmd = 0x%x: ERROR: (0x%02X: 0x%04X): %s: %s\n",
631 TWA_MESSAGE_SOURCE_CONTROLLER_ERROR
,
633 twa_find_msg_string(twa_error_table
, error
),
634 cmd_hdr
->err_specific_desc
);
637 bcopy(cmd_hdr
->sense_data
, &(ccb
->csio
.sense_data
),
638 TWA_SENSE_DATA_LENGTH
);
639 ccb
->csio
.sense_len
= TWA_SENSE_DATA_LENGTH
;
640 ccb
->ccb_h
.status
|= CAM_SCSI_STATUS_ERROR
| CAM_AUTOSNS_VALID
;
642 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
644 ccb
->csio
.scsi_status
= cmd
->status
;
645 /* If simq is frozen, unfreeze it. */
646 if (sc
->twa_state
& TWA_STATE_SIMQ_FROZEN
)
647 twa_allow_new_requests(sc
, (void *)ccb
);
650 ccb
->ccb_h
.status
&= ~CAM_SIM_QUEUED
;
657 * Function name: twa_drain_busy_queue
658 * Description: This function gets called after a controller reset.
659 * It errors back to CAM, all those requests that were
660 * pending with the firmware, at the time of the reset.
662 * Input: sc -- ptr to per ctlr structure
667 twa_drain_busy_queue(struct twa_softc
*sc
)
669 struct twa_request
*tr
;
672 /* Walk the busy queue. */
673 while ((tr
= twa_dequeue_busy(sc
))) {
674 twa_unmap_request(tr
);
675 if ((tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_INTERNAL
) ||
676 (tr
->tr_cmd_pkt_type
& TWA_CMD_PKT_TYPE_IOCTL
)) {
677 /* It's an internal/ioctl request. Simply free it. */
679 kfree(tr
->tr_data
, M_DEVBUF
);
681 if ((ccb
= tr
->tr_private
)) {
682 /* It's a SCSI request. Complete it. */
683 ccb
->ccb_h
.status
= CAM_SCSI_BUS_RESET
|
685 ccb
->ccb_h
.status
&= ~CAM_SIM_QUEUED
;
689 twa_release_request(tr
);
696 * Function name: twa_allow_new_requests
697 * Description: Sets the appropriate status bits in a ccb such that,
698 * when the ccb is completed by a call to xpt_done,
699 * CAM knows that it's ok to unfreeze the flow of new
700 * requests to this controller, if the flow is frozen.
702 * Input: sc -- ptr to per ctlr structure
703 * ccb -- ptr to CAM request
708 twa_allow_new_requests(struct twa_softc
*sc
, void *ccb
)
710 ((union ccb
*)(ccb
))->ccb_h
.status
|= CAM_RELEASE_SIMQ
;
711 sc
->twa_state
&= ~TWA_STATE_SIMQ_FROZEN
;
717 * Function name: twa_disallow_new_requests
718 * Description: Calls the appropriate CAM function, so as to freeze
719 * the flow of new requests from CAM to this controller.
721 * Input: sc -- ptr to per ctlr structure
726 twa_disallow_new_requests(struct twa_softc
*sc
)
728 xpt_freeze_simq(sc
->twa_sim
, 1);
729 sc
->twa_state
|= TWA_STATE_SIMQ_FROZEN
;