2 * Copyright (c) 2002 Adaptec, 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
26 * $FreeBSD: src/sys/dev/aac/aac_cam.c,v 1.2.2.4 2003/04/08 13:22:08 scottl Exp $
27 * $DragonFly: src/sys/dev/raid/aac/aac_cam.c,v 1.10 2008/05/18 20:30:23 pavalos Exp $
31 * CAM front-end for communicating with non-DASD devices
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/sysctl.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
43 #include <bus/cam/cam.h>
44 #include <bus/cam/cam_ccb.h>
45 #include <bus/cam/cam_debug.h>
46 #include <bus/cam/cam_sim.h>
47 #include <bus/cam/cam_xpt_sim.h>
48 #include <bus/cam/scsi/scsi_all.h>
49 #include <bus/cam/scsi/scsi_message.h>
53 #include <sys/devicestat.h>
57 #include <machine/md_var.h>
63 #include "aac_ioctl.h"
70 struct cam_path
*path
;
73 static int aac_cam_probe(device_t dev
);
74 static int aac_cam_attach(device_t dev
);
75 static int aac_cam_detach(device_t dev
);
76 static void aac_cam_action(struct cam_sim
*, union ccb
*);
77 static void aac_cam_poll(struct cam_sim
*);
78 static void aac_cam_complete(struct aac_command
*);
79 static u_int32_t
aac_cam_reset_bus(struct cam_sim
*, union ccb
*);
80 static u_int32_t
aac_cam_abort_ccb(struct cam_sim
*, union ccb
*);
81 static u_int32_t
aac_cam_term_io(struct cam_sim
*, union ccb
*);
83 static devclass_t aac_pass_devclass
;
85 static device_method_t aac_pass_methods
[] = {
86 DEVMETHOD(device_probe
, aac_cam_probe
),
87 DEVMETHOD(device_attach
, aac_cam_attach
),
88 DEVMETHOD(device_detach
, aac_cam_detach
),
92 static driver_t aac_pass_driver
= {
95 sizeof(struct aac_cam
)
98 DRIVER_MODULE(aacp
, aac
, aac_pass_driver
, aac_pass_devclass
, 0, 0);
99 MODULE_DEPEND(aacp
, cam
, 1, 1, 1);
101 MALLOC_DEFINE(M_AACCAM
, "aaccam", "AAC CAM info");
104 aac_cam_event(struct aac_softc
*sc
, struct aac_event
*event
, void *arg
)
106 struct aac_cam
*camsc
;
108 switch (event
->ev_type
) {
109 case AAC_EVENT_CMFREE
:
111 kfree(event
, M_AACCAM
);
112 xpt_release_simq(camsc
->sim
, 1);
115 device_printf(sc
->aac_dev
, "unknown event %d in aac_cam\n",
124 aac_cam_probe(device_t dev
)
132 aac_cam_detach(device_t dev
)
134 struct aac_cam
*camsc
;
137 camsc
= (struct aac_cam
*)device_get_softc(dev
);
141 xpt_async(AC_LOST_DEVICE
, camsc
->path
, NULL
);
142 xpt_free_path(camsc
->path
);
143 xpt_bus_deregister(cam_sim_path(camsc
->sim
));
144 cam_sim_free(camsc
->sim
);
152 * Register the driver as a CAM SIM
155 aac_cam_attach(device_t dev
)
157 struct cam_devq
*devq
;
159 struct cam_path
*path
;
160 struct aac_cam
*camsc
;
165 camsc
= (struct aac_cam
*)device_get_softc(dev
);
166 inf
= (struct aac_sim
*)device_get_ivars(dev
);
169 devq
= cam_simq_alloc(inf
->TargetsPerBus
);
173 sim
= cam_sim_alloc(aac_cam_action
, aac_cam_poll
, "aacp", camsc
,
174 device_get_unit(dev
), &sim_mplock
, 1, 1, devq
);
175 cam_simq_release(devq
);
180 /* Since every bus has it's own sim, every bus 'appears' as bus 0 */
181 if (xpt_bus_register(sim
, 0) != CAM_SUCCESS
) {
186 if (xpt_create_path(&path
, NULL
, cam_sim_path(sim
),
187 CAM_TARGET_WILDCARD
, CAM_LUN_WILDCARD
) != CAM_REQ_CMP
) {
188 xpt_bus_deregister(cam_sim_path(sim
));
200 aac_cam_action(struct cam_sim
*sim
, union ccb
*ccb
)
202 struct aac_cam
*camsc
;
203 struct aac_softc
*sc
;
204 struct aac_srb32
*srb
;
206 struct aac_command
*cm
;
210 camsc
= (struct aac_cam
*)cam_sim_softc(sim
);
211 sc
= camsc
->inf
->aac_sc
;
213 /* Synchronous ops, and ops that don't require communication with the
215 switch(ccb
->ccb_h
.func_code
) {
218 /* These are handled down below */
220 case XPT_CALC_GEOMETRY
:
222 struct ccb_calc_geometry
*ccg
;
224 u_int32_t secs_per_cylinder
;
227 size_mb
= ccg
->volume_size
/
228 ((1024L * 1024L) / ccg
->block_size
);
229 if (size_mb
>= (2 * 1024)) { /* 2GB */
231 ccg
->secs_per_track
= 63;
232 } else if (size_mb
>= (1 * 1024)) { /* 1GB */
234 ccg
->secs_per_track
= 32;
237 ccg
->secs_per_track
= 32;
239 secs_per_cylinder
= ccg
->heads
* ccg
->secs_per_track
;
240 ccg
->cylinders
= ccg
->volume_size
/ secs_per_cylinder
;
242 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
248 struct ccb_pathinq
*cpi
= &ccb
->cpi
;
250 cpi
->version_num
= 1;
251 cpi
->hba_inquiry
= PI_WIDE_16
;
252 cpi
->target_sprt
= 0;
254 /* Resetting via the passthrough causes problems. */
255 cpi
->hba_misc
= PIM_NOBUSRESET
;
256 cpi
->hba_eng_cnt
= 0;
257 cpi
->max_target
= camsc
->inf
->TargetsPerBus
;
258 cpi
->max_lun
= 8; /* Per the controller spec */
259 cpi
->initiator_id
= camsc
->inf
->InitiatorBusId
;
260 cpi
->bus_id
= camsc
->inf
->BusNumber
;
261 cpi
->base_transfer_speed
= 3300;
262 strncpy(cpi
->sim_vid
, "FreeBSD", SIM_IDLEN
);
263 strncpy(cpi
->hba_vid
, "Adaptec", HBA_IDLEN
);
264 strncpy(cpi
->dev_name
, cam_sim_name(sim
), DEV_IDLEN
);
265 cpi
->unit_number
= cam_sim_unit(sim
);
266 cpi
->transport
= XPORT_SPI
;
267 cpi
->transport_version
= 2;
268 cpi
->protocol
= PROTO_SCSI
;
269 cpi
->protocol_version
= SCSI_REV_2
;
270 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
274 case XPT_GET_TRAN_SETTINGS
:
276 struct ccb_trans_settings_scsi
*scsi
=
277 &ccb
->cts
.proto_specific
.scsi
;
278 struct ccb_trans_settings_spi
*spi
=
279 &ccb
->cts
.xport_specific
.spi
;
280 ccb
->cts
.protocol
= PROTO_SCSI
;
281 ccb
->cts
.protocol_version
= SCSI_REV_2
;
282 ccb
->cts
.transport
= XPORT_SPI
;
283 ccb
->cts
.transport_version
= 2;
284 if (ccb
->ccb_h
.target_lun
!= CAM_LUN_WILDCARD
) {
285 scsi
->valid
= CTS_SCSI_VALID_TQ
;
286 spi
->valid
|= CTS_SPI_VALID_DISC
;
290 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
294 case XPT_SET_TRAN_SETTINGS
:
295 ccb
->ccb_h
.status
= CAM_FUNC_NOTAVAIL
;
299 if (!(sc
->flags
& AAC_FLAGS_CAM_NORESET
)) {
300 ccb
->ccb_h
.status
= aac_cam_reset_bus(sim
, ccb
);
302 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
307 ccb
->ccb_h
.status
= aac_cam_abort_ccb(sim
, ccb
);
311 ccb
->ccb_h
.status
= aac_cam_term_io(sim
, ccb
);
315 device_printf(sc
->aac_dev
, "Unsupported command 0x%x\n",
316 ccb
->ccb_h
.func_code
);
317 ccb
->ccb_h
.status
= CAM_PROVIDE_FAIL
;
322 /* Async ops that require communcation with the controller */
324 AAC_LOCK_ACQUIRE(&sc
->aac_io_lock
);
325 if (aac_alloc_command(sc
, &cm
)) {
326 struct aac_event
*event
;
328 xpt_freeze_simq(sim
, 1);
329 ccb
->ccb_h
.status
= CAM_REQUEUE_REQ
;
331 event
= kmalloc(sizeof(struct aac_event
), M_AACCAM
,
333 event
->ev_callback
= aac_cam_event
;
334 event
->ev_arg
= camsc
;
335 event
->ev_type
= AAC_EVENT_CMFREE
;
336 aac_add_event(sc
, event
);
337 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
342 srb
= (struct aac_srb32
*)&fib
->data
[0];
345 switch (ccb
->ccb_h
.flags
& CAM_DIR_MASK
) {
347 srb
->flags
= AAC_SRB_FLAGS_DATA_IN
;
348 cm
->cm_flags
|= AAC_CMD_DATAIN
;
351 srb
->flags
= AAC_SRB_FLAGS_DATA_OUT
;
352 cm
->cm_flags
|= AAC_CMD_DATAOUT
;
355 srb
->flags
= AAC_SRB_FLAGS_NO_DATA_XFER
;
358 srb
->flags
= AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION
;
359 cm
->cm_flags
|= AAC_CMD_DATAIN
| AAC_CMD_DATAOUT
;
363 switch(ccb
->ccb_h
.func_code
) {
366 struct ccb_scsiio
*csio
= &ccb
->csio
;
368 srb
->function
= AAC_SRB_FUNC_EXECUTE_SCSI
;
371 * Copy the CDB into the SRB. It's only 6-16 bytes,
372 * so a copy is not too expensive.
374 srb
->cdb_len
= csio
->cdb_len
;
375 if (ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
376 bcopy(csio
->cdb_io
.cdb_ptr
, (u_int8_t
*)&srb
->cdb
[0],
379 bcopy(csio
->cdb_io
.cdb_bytes
, (u_int8_t
*)&srb
->cdb
[0],
382 /* Map the s/g list. XXX 32bit addresses only! */
383 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
) {
384 if ((ccb
->ccb_h
.flags
& CAM_SCATTER_VALID
) == 0) {
385 srb
->data_len
= csio
->dxfer_len
;
386 if (ccb
->ccb_h
.flags
& CAM_DATA_PHYS
) {
388 * XXX This isn't 64-bit clean.
389 * However, this condition is not
390 * normally used in CAM.
392 srb
->sg_map32
.SgCount
= 1;
393 srb
->sg_map32
.SgEntry
[0].SgAddress
=
394 (uint32_t)(uintptr_t)csio
->data_ptr
;
395 srb
->sg_map32
.SgEntry
[0].SgByteCount
=
399 * Arrange things so that the S/G
400 * map will get set up automagically
402 cm
->cm_data
= (void *)csio
->data_ptr
;
403 cm
->cm_datalen
= csio
->dxfer_len
;
404 cm
->cm_sgtable
= &srb
->sg_map32
;
407 /* XXX Need to handle multiple s/g elements */
408 panic("aac_cam: multiple s/g elements");
411 srb
->sg_map32
.SgCount
= 0;
412 srb
->sg_map32
.SgEntry
[0].SgByteCount
= 0;
419 if (!(sc
->flags
& AAC_FLAGS_CAM_NORESET
)) {
420 srb
->function
= AAC_SRB_FUNC_RESET_DEVICE
;
423 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
425 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
432 srb
->bus
= camsc
->inf
->BusNumber
; /* Bus number relative to the card */
433 srb
->target
= ccb
->ccb_h
.target_id
;
434 srb
->lun
= ccb
->ccb_h
.target_lun
;
435 srb
->timeout
= ccb
->ccb_h
.timeout
; /* XXX */
436 srb
->retry_limit
= 0;
438 cm
->cm_complete
= aac_cam_complete
;
439 cm
->cm_private
= ccb
;
440 cm
->cm_timestamp
= time_second
;
441 cm
->cm_queue
= AAC_ADAP_NORM_CMD_QUEUE
;
443 fib
->Header
.XferState
=
444 AAC_FIBSTATE_HOSTOWNED
|
445 AAC_FIBSTATE_INITIALISED
|
446 AAC_FIBSTATE_FROMHOST
|
447 AAC_FIBSTATE_REXPECTED
|
449 fib
->Header
.Command
= ScsiPortCommand
;
450 fib
->Header
.Size
= sizeof(struct aac_fib_header
) +
451 sizeof(struct aac_srb32
);
453 aac_enqueue_ready(cm
);
454 aac_startio(cm
->cm_sc
);
456 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
462 aac_cam_poll(struct cam_sim
*sim
)
465 * Pinging the interrupt routine isn't very safe, nor is it
466 * really necessary. Do nothing.
471 aac_cam_complete(struct aac_command
*cm
)
474 struct aac_srb_response
*srbr
;
475 struct aac_softc
*sc
;
480 ccb
= cm
->cm_private
;
481 srbr
= (struct aac_srb_response
*)&cm
->cm_fib
->data
[0];
483 if (srbr
->fib_status
!= 0) {
484 device_printf(sc
->aac_dev
, "Passthru FIB failed!\n");
485 ccb
->ccb_h
.status
= CAM_REQ_ABORTED
;
488 * The SRB error codes just happen to match the CAM error
489 * codes. How convienient!
491 ccb
->ccb_h
.status
= srbr
->srb_status
;
493 /* Take care of SCSI_IO ops. */
494 if (ccb
->ccb_h
.func_code
== XPT_SCSI_IO
) {
495 u_int8_t command
, device
;
497 ccb
->csio
.scsi_status
= srbr
->scsi_status
;
499 /* Take care of autosense */
500 if (srbr
->sense_len
) {
501 int sense_len
, scsi_sense_len
;
503 scsi_sense_len
= sizeof(struct scsi_sense_data
);
504 bzero(&ccb
->csio
.sense_data
, scsi_sense_len
);
505 sense_len
= (srbr
->sense_len
>
506 scsi_sense_len
) ? scsi_sense_len
:
508 bcopy(&srbr
->sense
[0], &ccb
->csio
.sense_data
,
510 ccb
->csio
.sense_len
= sense_len
;
511 ccb
->ccb_h
.status
|= CAM_AUTOSNS_VALID
;
512 /* scsi_sense_print(&ccb->csio); */
515 /* If this is an inquiry command, fake things out */
516 if (ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
517 command
= ccb
->csio
.cdb_io
.cdb_ptr
[0];
519 command
= ccb
->csio
.cdb_io
.cdb_bytes
[0];
521 if ((command
== INQUIRY
) &&
522 (ccb
->ccb_h
.status
== CAM_REQ_CMP
)) {
523 device
= ccb
->csio
.data_ptr
[0] & 0x1f;
525 * We want DASD and PROC devices to only be
526 * visible through the pass device.
528 if ((device
== T_DIRECT
) ||
529 (device
== T_PROCESSOR
) ||
530 (sc
->flags
& AAC_FLAGS_CAM_PASSONLY
))
531 ccb
->csio
.data_ptr
[0] =
532 ((device
& 0xe0) | T_NODEVICE
);
537 aac_release_command(cm
);
544 aac_cam_reset_bus(struct cam_sim
*sim
, union ccb
*ccb
)
547 struct aac_softc
*sc
;
548 struct aac_cam
*camsc
;
549 struct aac_vmioctl
*vmi
;
550 struct aac_resetbus
*rbc
;
553 camsc
= (struct aac_cam
*)cam_sim_softc(sim
);
554 sc
= camsc
->inf
->aac_sc
;
557 kprintf("Null sc?\n");
558 return (CAM_REQ_ABORTED
);
561 AAC_LOCK_ACQUIRE(&sc
->aac_io_lock
);
562 aac_alloc_sync_fib(sc
, &fib
);
564 vmi
= (struct aac_vmioctl
*)&fib
->data
[0];
565 bzero(vmi
, sizeof(struct aac_vmioctl
));
567 vmi
->Command
= VM_Ioctl
;
568 vmi
->ObjType
= FT_DRIVE
;
569 vmi
->MethId
= sc
->scsi_method_id
;
571 vmi
->IoctlCmd
= ResetBus
;
573 rbc
= (struct aac_resetbus
*)&vmi
->IoctlBuf
[0];
574 rbc
->BusNumber
= camsc
->inf
->BusNumber
;
576 e
= aac_sync_fib(sc
, ContainerCommand
, 0, fib
,
577 sizeof(struct aac_vmioctl
));
579 device_printf(sc
->aac_dev
,"Error %d sending ResetBus command\n",
581 aac_release_sync_fib(sc
);
582 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
583 return (CAM_REQ_ABORTED
);
586 aac_release_sync_fib(sc
);
587 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
588 return (CAM_REQ_CMP
);
592 aac_cam_abort_ccb(struct cam_sim
*sim
, union ccb
*ccb
)
594 return (CAM_UA_ABORT
);
598 aac_cam_term_io(struct cam_sim
*sim
, union ccb
*ccb
)
600 return (CAM_UA_TERMIO
);