2 * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
3 * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer,
11 * without modification, immediately at the beginning of the file.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/cam/scsi/scsi_pass.c,v 1.19 2000/01/17 06:27:37 mjacob Exp $
28 * $DragonFly: src/sys/bus/cam/scsi/scsi_pass.c,v 1.27 2008/05/18 20:30:20 pavalos Exp $
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/types.h>
36 #include <sys/malloc.h>
37 #include <sys/fcntl.h>
40 #include <sys/errno.h>
41 #include <sys/devicestat.h>
43 #include <sys/thread2.h>
46 #include "../cam_ccb.h"
47 #include "../cam_extend.h"
48 #include "../cam_periph.h"
49 #include "../cam_queue.h"
50 #include "../cam_xpt_periph.h"
51 #include "../cam_debug.h"
52 #include "../cam_sim.h"
55 #include "scsi_message.h"
57 #include "scsi_pass.h"
60 PASS_FLAG_OPEN
= 0x01,
61 PASS_FLAG_LOCKED
= 0x02,
62 PASS_FLAG_INVALID
= 0x04
74 #define ccb_type ppriv_field0
75 #define ccb_bio ppriv_ptr1
82 struct devstat device_stats
;
85 #define PASS_CDEV_MAJOR 31
87 static d_open_t passopen
;
88 static d_close_t passclose
;
89 static d_ioctl_t passioctl
;
91 static periph_init_t passinit
;
92 static periph_ctor_t passregister
;
93 static periph_oninv_t passoninvalidate
;
94 static periph_dtor_t passcleanup
;
95 static periph_start_t passstart
;
96 static void passasync(void *callback_arg
, u_int32_t code
,
97 struct cam_path
*path
, void *arg
);
98 static void passdone(struct cam_periph
*periph
,
100 static int passerror(union ccb
*ccb
, u_int32_t cam_flags
,
101 u_int32_t sense_flags
);
102 static int passsendccb(struct cam_periph
*periph
, union ccb
*ccb
,
105 static struct periph_driver passdriver
=
108 TAILQ_HEAD_INITIALIZER(passdriver
.units
), /* generation */ 0
111 PERIPHDRIVER_DECLARE(pass
, passdriver
);
113 static struct dev_ops pass_ops
= {
114 { "pass", PASS_CDEV_MAJOR
, 0 },
116 .d_close
= passclose
,
119 .d_ioctl
= passioctl
,
120 .d_strategy
= nostrategy
,
123 static struct extend_array
*passperiphs
;
131 * Create our extend array for storing the devices we attach to.
133 passperiphs
= cam_extend_new();
134 if (passperiphs
== NULL
) {
135 kprintf("passm: Failed to alloc extend array!\n");
140 * Install a global async callback. This callback will
141 * receive async callbacks like "new device found".
143 status
= xpt_register_async(AC_FOUND_DEVICE
, passasync
, NULL
, NULL
);
145 if (status
!= CAM_REQ_CMP
) {
146 kprintf("pass: Failed to attach master async callback "
147 "due to status 0x%x!\n", status
);
153 passoninvalidate(struct cam_periph
*periph
)
155 struct pass_softc
*softc
;
157 softc
= (struct pass_softc
*)periph
->softc
;
160 * De-register any async callbacks.
162 xpt_register_async(0, passasync
, periph
, periph
->path
);
164 softc
->flags
|= PASS_FLAG_INVALID
;
167 xpt_print(periph
->path
, "lost device\n");
173 passcleanup(struct cam_periph
*periph
)
175 struct pass_softc
*softc
;
177 softc
= (struct pass_softc
*)periph
->softc
;
179 devstat_remove_entry(&softc
->device_stats
);
181 cam_extend_release(passperiphs
, periph
->unit_number
);
184 xpt_print(periph
->path
, "removing device entry\n");
186 dev_ops_remove(&pass_ops
, -1, periph
->unit_number
);
187 kfree(softc
, M_DEVBUF
);
191 passasync(void *callback_arg
, u_int32_t code
,
192 struct cam_path
*path
, void *arg
)
194 struct cam_periph
*periph
;
197 periph
= (struct cam_periph
*)callback_arg
;
200 case AC_FOUND_DEVICE
:
202 struct ccb_getdev
*cgd
;
205 cgd
= (struct ccb_getdev
*)arg
;
210 * Allocate a peripheral instance for
211 * this device and start the probe
214 sim
= xpt_path_sim(cgd
->ccb_h
.path
);
215 status
= cam_periph_alloc(passregister
, passoninvalidate
,
216 passcleanup
, passstart
, "pass",
217 CAM_PERIPH_BIO
, cgd
->ccb_h
.path
,
218 passasync
, AC_FOUND_DEVICE
, cgd
);
220 if (status
!= CAM_REQ_CMP
221 && status
!= CAM_REQ_INPROG
) {
222 const struct cam_status_entry
*entry
;
224 entry
= cam_fetch_status_entry(status
);
226 kprintf("passasync: Unable to attach new device "
227 "due to status %#x: %s\n", status
, entry
?
228 entry
->status_text
: "Unknown");
234 cam_periph_async(periph
, code
, path
, arg
);
240 passregister(struct cam_periph
*periph
, void *arg
)
242 struct pass_softc
*softc
;
243 struct ccb_getdev
*cgd
;
246 cgd
= (struct ccb_getdev
*)arg
;
247 if (periph
== NULL
) {
248 kprintf("passregister: periph was NULL!!\n");
249 return(CAM_REQ_CMP_ERR
);
253 kprintf("passregister: no getdev CCB, can't register device\n");
254 return(CAM_REQ_CMP_ERR
);
257 softc
= kmalloc(sizeof(*softc
), M_DEVBUF
, M_INTWAIT
| M_ZERO
);
258 softc
->state
= PASS_STATE_NORMAL
;
259 softc
->pd_type
= SID_TYPE(&cgd
->inq_data
);
261 periph
->softc
= softc
;
262 cam_extend_set(passperiphs
, periph
->unit_number
, periph
);
265 * We pass in 0 for a blocksize, since we don't
266 * know what the blocksize of this device is, if
267 * it even has a blocksize.
269 CAM_SIM_UNLOCK(periph
->sim
);
270 no_tags
= (cgd
->inq_data
.flags
& SID_CmdQue
) == 0;
271 devstat_add_entry(&softc
->device_stats
, "pass", periph
->unit_number
, 0,
273 | (no_tags
? DEVSTAT_NO_ORDERED_TAGS
: 0),
275 DEVSTAT_TYPE_IF_SCSI
|
277 DEVSTAT_PRIORITY_PASS
);
279 /* Register the device */
280 dev_ops_add(&pass_ops
, -1, periph
->unit_number
);
281 make_dev(&pass_ops
, periph
->unit_number
, UID_ROOT
,
282 GID_OPERATOR
, 0600, "%s%d", periph
->periph_name
,
283 periph
->unit_number
);
284 CAM_SIM_LOCK(periph
->sim
);
286 * Add an async callback so that we get
287 * notified if this device goes away.
289 xpt_register_async(AC_LOST_DEVICE
, passasync
, periph
, periph
->path
);
292 xpt_announce_periph(periph
, NULL
);
298 passopen(struct dev_open_args
*ap
)
300 cdev_t dev
= ap
->a_head
.a_dev
;
301 struct cam_periph
*periph
;
302 struct pass_softc
*softc
;
305 error
= 0; /* default to no error */
307 /* unit = dkunit(dev); */
308 /* XXX KDM fix this */
309 unit
= minor(dev
) & 0xff;
311 periph
= cam_extend_get(passperiphs
, unit
);
313 if (cam_periph_acquire(periph
) != CAM_REQ_CMP
)
316 cam_periph_lock(periph
);
318 softc
= (struct pass_softc
*)periph
->softc
;
320 if (softc
->flags
& PASS_FLAG_INVALID
) {
321 cam_periph_unlock(periph
);
322 cam_periph_release(periph
);
327 * Don't allow access when we're running at a high securelevel.
329 if (securelevel
> 1) {
330 cam_periph_unlock(periph
);
331 cam_periph_release(periph
);
336 * Only allow read-write access.
338 if (((ap
->a_oflags
& FWRITE
) == 0) || ((ap
->a_oflags
& FREAD
) == 0)) {
339 cam_periph_unlock(periph
);
340 cam_periph_release(periph
);
345 * We don't allow nonblocking access.
347 if ((ap
->a_oflags
& O_NONBLOCK
) != 0) {
348 xpt_print(periph
->path
, "can't do nonblocking access\n");
349 cam_periph_unlock(periph
);
350 cam_periph_release(periph
);
354 if ((softc
->flags
& PASS_FLAG_OPEN
) == 0) {
355 softc
->flags
|= PASS_FLAG_OPEN
;
357 /* Device closes aren't symmertical, so fix up the refcount */
358 cam_periph_release(periph
);
361 cam_periph_unlock(periph
);
367 passclose(struct dev_close_args
*ap
)
369 cdev_t dev
= ap
->a_head
.a_dev
;
370 struct cam_periph
*periph
;
371 struct pass_softc
*softc
;
374 /* unit = dkunit(dev); */
375 /* XXX KDM fix this */
376 unit
= minor(dev
) & 0xff;
378 periph
= cam_extend_get(passperiphs
, unit
);
382 cam_periph_lock(periph
);
384 softc
= (struct pass_softc
*)periph
->softc
;
385 softc
->flags
&= ~PASS_FLAG_OPEN
;
387 cam_periph_unlock(periph
);
388 cam_periph_release(periph
);
394 passstart(struct cam_periph
*periph
, union ccb
*start_ccb
)
396 struct pass_softc
*softc
;
398 softc
= (struct pass_softc
*)periph
->softc
;
400 switch (softc
->state
) {
401 case PASS_STATE_NORMAL
:
402 start_ccb
->ccb_h
.ccb_type
= PASS_CCB_WAITING
;
403 SLIST_INSERT_HEAD(&periph
->ccb_list
, &start_ccb
->ccb_h
,
405 periph
->immediate_priority
= CAM_PRIORITY_NONE
;
406 wakeup(&periph
->ccb_list
);
412 passdone(struct cam_periph
*periph
, union ccb
*done_ccb
)
414 struct pass_softc
*softc
;
415 struct ccb_scsiio
*csio
;
417 softc
= (struct pass_softc
*)periph
->softc
;
418 csio
= &done_ccb
->csio
;
419 switch (csio
->ccb_h
.ccb_type
) {
420 case PASS_CCB_WAITING
:
421 /* Caller will release the CCB */
422 wakeup(&done_ccb
->ccb_h
.cbfcnp
);
425 xpt_release_ccb(done_ccb
);
429 passioctl(struct dev_ioctl_args
*ap
)
431 cdev_t dev
= ap
->a_head
.a_dev
;
432 caddr_t addr
= ap
->a_data
;
433 struct cam_periph
*periph
;
434 struct pass_softc
*softc
;
439 /* unit = dkunit(dev); */
440 /* XXX KDM fix this */
441 unit
= minor(dev
) & 0xff;
443 periph
= cam_extend_get(passperiphs
, unit
);
448 cam_periph_lock(periph
);
449 softc
= (struct pass_softc
*)periph
->softc
;
461 inccb
= (union ccb
*)addr
;
464 * Some CCB types, like scan bus and scan lun can only go
465 * through the transport layer device.
467 if (inccb
->ccb_h
.func_code
& XPT_FC_XPT_ONLY
) {
468 xpt_print(periph
->path
, "CCB function code %#x is "
469 "restricted to the XPT device\n",
470 inccb
->ccb_h
.func_code
);
476 * Non-immediate CCBs need a CCB from the per-device pool
477 * of CCBs, which is scheduled by the transport layer.
478 * Immediate CCBs and user-supplied CCBs should just be
481 if ((inccb
->ccb_h
.func_code
& XPT_FC_QUEUED
)
482 && ((inccb
->ccb_h
.func_code
& XPT_FC_USER_CCB
) == 0)) {
483 ccb
= cam_periph_getccb(periph
,
484 inccb
->ccb_h
.pinfo
.priority
);
487 ccb
= xpt_alloc_ccb();
490 xpt_setup_ccb(&ccb
->ccb_h
, periph
->path
,
491 inccb
->ccb_h
.pinfo
.priority
);
496 xpt_print(periph
->path
, "unable to allocate CCB\n");
501 error
= passsendccb(periph
, ccb
, inccb
);
506 xpt_release_ccb(ccb
);
511 error
= cam_periph_ioctl(periph
, ap
->a_cmd
, addr
, passerror
);
515 cam_periph_unlock(periph
);
520 * Generally, "ccb" should be the CCB supplied by the kernel. "inccb"
521 * should be the CCB that is copied in from the user.
524 passsendccb(struct cam_periph
*periph
, union ccb
*ccb
, union ccb
*inccb
)
526 struct pass_softc
*softc
;
527 struct cam_periph_map_info mapinfo
;
528 int error
, need_unmap
;
530 softc
= (struct pass_softc
*)periph
->softc
;
535 * There are some fields in the CCB header that need to be
536 * preserved, the rest we get from the user.
538 xpt_merge_ccb(ccb
, inccb
);
541 * There's no way for the user to have a completion
542 * function, so we put our own completion function in here.
544 ccb
->ccb_h
.cbfcnp
= passdone
;
547 * We only attempt to map the user memory into kernel space
548 * if they haven't passed in a physical memory pointer,
549 * and if there is actually an I/O operation to perform.
550 * Right now cam_periph_mapmem() only supports SCSI and device
551 * match CCBs. For the SCSI CCBs, we only pass the CCB in if
552 * there's actually data to map. cam_periph_mapmem() will do the
553 * right thing, even if there isn't data to map, but since CCBs
554 * without data are a reasonably common occurance (e.g. test unit
555 * ready), it will save a few cycles if we check for it here.
557 if (((ccb
->ccb_h
.flags
& CAM_DATA_PHYS
) == 0)
558 && (((ccb
->ccb_h
.func_code
== XPT_SCSI_IO
)
559 && ((ccb
->ccb_h
.flags
& CAM_DIR_MASK
) != CAM_DIR_NONE
))
560 || (ccb
->ccb_h
.func_code
== XPT_DEV_MATCH
))) {
562 bzero(&mapinfo
, sizeof(mapinfo
));
565 * cam_periph_mapmem calls into proc and vm functions that can
566 * sleep as well as trigger I/O, so we can't hold the lock.
567 * Dropping it here is reasonably safe.
569 cam_periph_unlock(periph
);
570 error
= cam_periph_mapmem(ccb
, &mapinfo
);
571 cam_periph_lock(periph
);
574 * cam_periph_mapmem returned an error, we can't continue.
575 * Return the error to the user.
581 * We successfully mapped the memory in, so we need to
582 * unmap it when the transaction is done.
588 * If the user wants us to perform any error recovery, then honor
589 * that request. Otherwise, it's up to the user to perform any
592 error
= cam_periph_runccb(ccb
,
593 (ccb
->ccb_h
.flags
& CAM_PASS_ERR_RECOVER
) ?
595 /* cam_flags */ CAM_RETRY_SELTO
,
596 /* sense_flags */SF_RETRY_UA
,
597 &softc
->device_stats
);
600 cam_periph_unmapmem(ccb
, &mapinfo
);
602 ccb
->ccb_h
.cbfcnp
= NULL
;
603 ccb
->ccb_h
.periph_priv
= inccb
->ccb_h
.periph_priv
;
604 bcopy(ccb
, inccb
, sizeof(union ccb
));
610 passerror(union ccb
*ccb
, u_int32_t cam_flags
, u_int32_t sense_flags
)
612 struct cam_periph
*periph
;
613 struct pass_softc
*softc
;
615 periph
= xpt_path_periph(ccb
->ccb_h
.path
);
616 softc
= (struct pass_softc
*)periph
->softc
;
618 return(cam_periph_error(ccb
, cam_flags
, sense_flags
,