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.8 2008/01/20 03:40:35 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
), 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 #ifdef CAM_NEW_TRAN_CODE
267 cpi
->transport
= XPORT_SPI
;
268 cpi
->transport_version
= 2;
269 cpi
->protocol
= PROTO_SCSI
;
270 cpi
->protocol_version
= SCSI_REV_2
;
272 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
276 case XPT_GET_TRAN_SETTINGS
:
278 #ifdef CAM_NEW_TRAN_CODE
279 struct ccb_trans_settings_scsi
*scsi
=
280 &ccb
->cts
.proto_specific
.scsi
;
281 struct ccb_trans_settings_spi
*spi
=
282 &ccb
->cts
.xport_specific
.spi
;
283 ccb
->cts
.protocol
= PROTO_SCSI
;
284 ccb
->cts
.protocol_version
= SCSI_REV_2
;
285 ccb
->cts
.transport
= XPORT_SPI
;
286 ccb
->cts
.transport_version
= 2;
287 if (ccb
->ccb_h
.target_lun
!= CAM_LUN_WILDCARD
) {
288 scsi
->valid
= CTS_SCSI_VALID_TQ
;
289 spi
->valid
|= CTS_SPI_VALID_DISC
;
294 ccb
->cts
.flags
&= ~(CCB_TRANS_DISC_ENB
| CCB_TRANS_TAG_ENB
);
295 ccb
->cts
.valid
= CCB_TRANS_DISC_VALID
| CCB_TRANS_TQ_VALID
;
297 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
301 case XPT_SET_TRAN_SETTINGS
:
302 ccb
->ccb_h
.status
= CAM_FUNC_NOTAVAIL
;
306 if (!(sc
->flags
& AAC_FLAGS_CAM_NORESET
)) {
307 ccb
->ccb_h
.status
= aac_cam_reset_bus(sim
, ccb
);
309 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
314 ccb
->ccb_h
.status
= aac_cam_abort_ccb(sim
, ccb
);
318 ccb
->ccb_h
.status
= aac_cam_term_io(sim
, ccb
);
322 device_printf(sc
->aac_dev
, "Unsupported command 0x%x\n",
323 ccb
->ccb_h
.func_code
);
324 ccb
->ccb_h
.status
= CAM_PROVIDE_FAIL
;
329 /* Async ops that require communcation with the controller */
331 AAC_LOCK_ACQUIRE(&sc
->aac_io_lock
);
332 if (aac_alloc_command(sc
, &cm
)) {
333 struct aac_event
*event
;
335 xpt_freeze_simq(sim
, 1);
336 ccb
->ccb_h
.status
= CAM_REQUEUE_REQ
;
338 event
= kmalloc(sizeof(struct aac_event
), M_AACCAM
,
340 event
->ev_callback
= aac_cam_event
;
341 event
->ev_arg
= camsc
;
342 event
->ev_type
= AAC_EVENT_CMFREE
;
343 aac_add_event(sc
, event
);
344 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
349 srb
= (struct aac_srb32
*)&fib
->data
[0];
352 switch (ccb
->ccb_h
.flags
& CAM_DIR_MASK
) {
354 srb
->flags
= AAC_SRB_FLAGS_DATA_IN
;
355 cm
->cm_flags
|= AAC_CMD_DATAIN
;
358 srb
->flags
= AAC_SRB_FLAGS_DATA_OUT
;
359 cm
->cm_flags
|= AAC_CMD_DATAOUT
;
362 srb
->flags
= AAC_SRB_FLAGS_NO_DATA_XFER
;
365 srb
->flags
= AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION
;
366 cm
->cm_flags
|= AAC_CMD_DATAIN
| AAC_CMD_DATAOUT
;
370 switch(ccb
->ccb_h
.func_code
) {
373 struct ccb_scsiio
*csio
= &ccb
->csio
;
375 srb
->function
= AAC_SRB_FUNC_EXECUTE_SCSI
;
378 * Copy the CDB into the SRB. It's only 6-16 bytes,
379 * so a copy is not too expensive.
381 srb
->cdb_len
= csio
->cdb_len
;
382 if (ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
383 bcopy(csio
->cdb_io
.cdb_ptr
, (u_int8_t
*)&srb
->cdb
[0],
386 bcopy(csio
->cdb_io
.cdb_bytes
, (u_int8_t
*)&srb
->cdb
[0],
389 /* Map the s/g list. XXX 32bit addresses only! */
390 if ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
) {
391 if ((ccb
->ccb_h
.flags
& CAM_SCATTER_VALID
) == 0) {
392 srb
->data_len
= csio
->dxfer_len
;
393 if (ccb
->ccb_h
.flags
& CAM_DATA_PHYS
) {
395 * XXX This isn't 64-bit clean.
396 * However, this condition is not
397 * normally used in CAM.
399 srb
->sg_map32
.SgCount
= 1;
400 srb
->sg_map32
.SgEntry
[0].SgAddress
=
401 (uint32_t)(uintptr_t)csio
->data_ptr
;
402 srb
->sg_map32
.SgEntry
[0].SgByteCount
=
406 * Arrange things so that the S/G
407 * map will get set up automagically
409 cm
->cm_data
= (void *)csio
->data_ptr
;
410 cm
->cm_datalen
= csio
->dxfer_len
;
411 cm
->cm_sgtable
= &srb
->sg_map32
;
414 /* XXX Need to handle multiple s/g elements */
415 panic("aac_cam: multiple s/g elements");
418 srb
->sg_map32
.SgCount
= 0;
419 srb
->sg_map32
.SgEntry
[0].SgByteCount
= 0;
426 if (!(sc
->flags
& AAC_FLAGS_CAM_NORESET
)) {
427 srb
->function
= AAC_SRB_FUNC_RESET_DEVICE
;
430 ccb
->ccb_h
.status
= CAM_REQ_CMP
;
432 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
439 srb
->bus
= camsc
->inf
->BusNumber
; /* Bus number relative to the card */
440 srb
->target
= ccb
->ccb_h
.target_id
;
441 srb
->lun
= ccb
->ccb_h
.target_lun
;
442 srb
->timeout
= ccb
->ccb_h
.timeout
; /* XXX */
443 srb
->retry_limit
= 0;
445 cm
->cm_complete
= aac_cam_complete
;
446 cm
->cm_private
= ccb
;
447 cm
->cm_timestamp
= time_second
;
448 cm
->cm_queue
= AAC_ADAP_NORM_CMD_QUEUE
;
450 fib
->Header
.XferState
=
451 AAC_FIBSTATE_HOSTOWNED
|
452 AAC_FIBSTATE_INITIALISED
|
453 AAC_FIBSTATE_FROMHOST
|
454 AAC_FIBSTATE_REXPECTED
|
456 fib
->Header
.Command
= ScsiPortCommand
;
457 fib
->Header
.Size
= sizeof(struct aac_fib_header
) +
458 sizeof(struct aac_srb32
);
460 aac_enqueue_ready(cm
);
461 aac_startio(cm
->cm_sc
);
463 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
469 aac_cam_poll(struct cam_sim
*sim
)
472 * Pinging the interrupt routine isn't very safe, nor is it
473 * really necessary. Do nothing.
478 aac_cam_complete(struct aac_command
*cm
)
481 struct aac_srb_response
*srbr
;
482 struct aac_softc
*sc
;
487 ccb
= cm
->cm_private
;
488 srbr
= (struct aac_srb_response
*)&cm
->cm_fib
->data
[0];
490 if (srbr
->fib_status
!= 0) {
491 device_printf(sc
->aac_dev
, "Passthru FIB failed!\n");
492 ccb
->ccb_h
.status
= CAM_REQ_ABORTED
;
495 * The SRB error codes just happen to match the CAM error
496 * codes. How convienient!
498 ccb
->ccb_h
.status
= srbr
->srb_status
;
500 /* Take care of SCSI_IO ops. */
501 if (ccb
->ccb_h
.func_code
== XPT_SCSI_IO
) {
502 u_int8_t command
, device
;
504 ccb
->csio
.scsi_status
= srbr
->scsi_status
;
506 /* Take care of autosense */
507 if (srbr
->sense_len
) {
508 int sense_len
, scsi_sense_len
;
510 scsi_sense_len
= sizeof(struct scsi_sense_data
);
511 bzero(&ccb
->csio
.sense_data
, scsi_sense_len
);
512 sense_len
= (srbr
->sense_len
>
513 scsi_sense_len
) ? scsi_sense_len
:
515 bcopy(&srbr
->sense
[0], &ccb
->csio
.sense_data
,
517 ccb
->csio
.sense_len
= sense_len
;
518 ccb
->ccb_h
.status
|= CAM_AUTOSNS_VALID
;
519 /* scsi_sense_print(&ccb->csio); */
522 /* If this is an inquiry command, fake things out */
523 if (ccb
->ccb_h
.flags
& CAM_CDB_POINTER
)
524 command
= ccb
->csio
.cdb_io
.cdb_ptr
[0];
526 command
= ccb
->csio
.cdb_io
.cdb_bytes
[0];
528 if ((command
== INQUIRY
) &&
529 (ccb
->ccb_h
.status
== CAM_REQ_CMP
)) {
530 device
= ccb
->csio
.data_ptr
[0] & 0x1f;
532 * We want DASD and PROC devices to only be
533 * visible through the pass device.
535 if ((device
== T_DIRECT
) ||
536 (device
== T_PROCESSOR
) ||
537 (sc
->flags
& AAC_FLAGS_CAM_PASSONLY
))
538 ccb
->csio
.data_ptr
[0] =
539 ((device
& 0xe0) | T_NODEVICE
);
544 aac_release_command(cm
);
551 aac_cam_reset_bus(struct cam_sim
*sim
, union ccb
*ccb
)
554 struct aac_softc
*sc
;
555 struct aac_cam
*camsc
;
556 struct aac_vmioctl
*vmi
;
557 struct aac_resetbus
*rbc
;
560 camsc
= (struct aac_cam
*)cam_sim_softc(sim
);
561 sc
= camsc
->inf
->aac_sc
;
564 kprintf("Null sc?\n");
565 return (CAM_REQ_ABORTED
);
568 AAC_LOCK_ACQUIRE(&sc
->aac_io_lock
);
569 aac_alloc_sync_fib(sc
, &fib
);
571 vmi
= (struct aac_vmioctl
*)&fib
->data
[0];
572 bzero(vmi
, sizeof(struct aac_vmioctl
));
574 vmi
->Command
= VM_Ioctl
;
575 vmi
->ObjType
= FT_DRIVE
;
576 vmi
->MethId
= sc
->scsi_method_id
;
578 vmi
->IoctlCmd
= ResetBus
;
580 rbc
= (struct aac_resetbus
*)&vmi
->IoctlBuf
[0];
581 rbc
->BusNumber
= camsc
->inf
->BusNumber
;
583 e
= aac_sync_fib(sc
, ContainerCommand
, 0, fib
,
584 sizeof(struct aac_vmioctl
));
586 device_printf(sc
->aac_dev
,"Error %d sending ResetBus command\n",
588 aac_release_sync_fib(sc
);
589 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
590 return (CAM_REQ_ABORTED
);
593 aac_release_sync_fib(sc
);
594 AAC_LOCK_RELEASE(&sc
->aac_io_lock
);
595 return (CAM_REQ_CMP
);
599 aac_cam_abort_ccb(struct cam_sim
*sim
, union ccb
*ccb
)
601 return (CAM_UA_ABORT
);
605 aac_cam_term_io(struct cam_sim
*sim
, union ccb
*ccb
)
607 return (CAM_UA_TERMIO
);