Rewrite of the CAM error recovery code.

Some of the major changes include:

	- The SCSI error handling portion of cam_periph_error() has
	  been broken out into a number of subfunctions to better
	  modularize the code that handles the hierarchy of SCSI errors.
	  As a result, the code is now much easier to read.

	- String handling and error printing has been significantly
	  revamped.  We now use sbufs to do string formatting instead
	  of using printfs (for the kernel) and snprintf/strncat (for
	  userland) as before.

	  There is a new catchall error printing routine,
	  cam_error_print() and its string-based counterpart,
	  cam_error_string() that allow the kernel and userland
	  applications to pass in a CCB and have errors printed out
	  properly, whether or not they're SCSI errors.  Among other
	  things, this helped eliminate a fair amount of duplicate code
	  in camcontrol.

	  We now print out more information than before, including
	  the CAM status and SCSI status and the error recovery action
	  taken to remedy the problem.

	- sbufs are now available in userland, via libsbuf.  This
	  change was necessary since most of the error printing code
	  is shared between libcam and the kernel.

	- A new transfer settings interface is included in this checkin.
	  This code is #ifdef'ed out, and is primarily intended to aid
	  discussion with HBA driver authors on the final form the
	  interface should take.  There is example code in the ahc(4)
	  driver that implements the HBA driver side of the new
	  interface.  The new transfer settings code won't be enabled
	  until we're ready to switch all HBA drivers over to the new
	  interface.

src/Makefile.inc1,
lib/Makefile:		Add libsbuf.  It must be built before libcam,
			since libcam uses sbuf routines.

libcam/Makefile:	libcam now depends on libsbuf.

libsbuf/Makefile:	Add a makefile for libsbuf.  This pulls in the
			sbuf sources from sys/kern.

bsd.libnames.mk:	Add LIBSBUF.

camcontrol/Makefile:	Add -lsbuf.  Since camcontrol is statically
			linked, we can't depend on the dynamic linker
			to pull in libsbuf.

camcontrol.c:		Use cam_error_print() instead of checking for
			CAM_SCSI_STATUS_ERROR on every failed CCB.

sbuf.9:			Change the prototypes for sbuf_cat() and
			sbuf_cpy() so that the source string is now a
			const char *.  This is more in line wth the
			standard system string functions, and helps
			eliminate warnings when dealing with a const
			source buffer.

			Fix a typo.

cam.c:			Add description strings for the various CAM
			error status values, as well as routines to
			look up those strings.

			Add new cam_error_string() and
			cam_error_print() routines for userland and
			the kernel.

cam.h:			Add a new CAM flag, CAM_RETRY_SELTO.

			Add enumerated types for the various options
			available with cam_error_print() and
			cam_error_string().

cam_ccb.h:		Add new transfer negotiation structures/types.

			Change inq_len in the ccb_getdev structure to
			be "reserved".  This field has never been
			filled in, and will be removed when we next
			bump the CAM version.

cam_debug.h:		Fix typo.

cam_periph.c:		Modularize cam_periph_error().  The SCSI error
			handling part of cam_periph_error() is now
			in camperiphscsistatuserror() and
			camperiphscsisenseerror().

			In cam_periph_lock(), increase the reference
			count on the periph while we wait for our lock
			attempt to succeed so that the periph won't go
			away while we're sleeping.

cam_xpt.c:		Add new transfer negotiation code.  (ifdefed
			out)

			Add a new function, xpt_path_string().  This
			is a string/sbuf analog to xpt_print_path().

scsi_all.c:		Revamp string handing and error printing code.
			We now use sbufs for much of the string
			formatting code.  More of that code is shared
			between userland the kernel.

scsi_all.h:		Get rid of SS_TURSTART, it wasn't terribly
			useful in the first place.

			Add a new error action, SS_REQSENSE.  (Send a
			request sense and then retry the command.)
			This is useful when the controller hasn't
			performed autosense for some reason.

			Change the default actions around a bit.

scsi_cd.c,
scsi_da.c,
scsi_pt.c,
scsi_ses.c:		SF_RETRY_SELTO -> CAM_RETRY_SELTO.  Selection
			timeouts shouldn't be covered by a sense flag.

scsi_pass.[ch]:		SF_RETRY_SELTO -> CAM_RETRY_SELTO.

			Get rid of the last vestiges of a read/write
			interface.

libkern/bsearch.c,
sys/libkern.h,
conf/files:		Add bsearch.c, which is needed for some of the
			new table lookup routines.

aic7xxx_freebsd.c:	Define AHC_NEW_TRAN_SETTINGS if
			CAM_NEW_TRAN_CODE is defined.

sbuf.h,
subr_sbuf.c:		Add the appropriate #ifdefs so sbufs can
			compile and run in userland.

			Change sbuf_printf() to use vsnprintf()
			instead of kvprintf(), which is only available
			in the kernel.

			Change the source string for sbuf_cpy() and
			sbuf_cat() to be a const char *.

			Add __BEGIN_DECLS and __END_DECLS around
			function prototypes since they're now exported
			to userland.

kdump/mkioctls:		Include stdio.h before cam.h since cam.h now
			includes a function with a FILE * argument.

Submitted by:	gibbs (mostly)
Reviewed by:	jdp, marcel (libsbuf makefile changes)
Reviewed by:	des (sbuf changes)
Reviewed by:	ken
This commit is contained in:
Kenneth D. Merry 2001-03-27 05:45:52 +00:00
parent 110a013333
commit 3393f8daa3
33 changed files with 2829 additions and 2074 deletions

View File

@ -695,6 +695,7 @@ includes:
cd ${.CURDIR}/lib/libpcap; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/libradius; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/librpcsvc; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/libsbuf; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/libskey; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/libstand; ${MAKE} beforeinstall
cd ${.CURDIR}/lib/libtacplus; ${MAKE} beforeinstall
@ -713,6 +714,7 @@ includes:
#
# lib*: csu libgcc_pic
# libatm: libmd
# libcam: libsbuf
# libcrypt: libmd
# libdialog: libncurses
# libedit: libncurses
@ -774,8 +776,8 @@ libraries:
.for _lib in ${_csu} gnu/lib/csu gnu/lib/libgcc lib/libmd lib/libcrypt \
${_secure_lib} ${_kerberosIV_lib} \
${_kerberos5_lib} lib/libcom_err ${_libm} lib/libncurses \
lib/libopie lib/libradius lib/libskey lib/libtacplus lib/libutil \
lib/libz lib gnu/lib ${_libperl} usr.bin/lex/lib ${_libkeycap}
lib/libopie lib/libradius lib/libsbuf lib/libskey lib/libtacplus \
lib/libutil lib/libz lib gnu/lib ${_libperl} usr.bin/lex/lib ${_libkeycap}
.if exists(${.CURDIR}/${_lib})
cd ${.CURDIR}/${_lib}; \
${MAKE} depend; \

View File

@ -16,11 +16,12 @@
# libskey must be built before libpam.
# libtacplus must be built before libpam.
# libutil must be built before libpam.
# libsbuf must be built before libcam.
#
# Otherwise, the SUBDIR list should be in alphabetical order.
SUBDIR= ${_csu} libcom_err libcrypt msun libmd \
libncurses libradius libskey libtacplus libutil \
libncurses libradius libskey libtacplus libutil libsbuf \
${_compat} libalias libatm ${_libbind} libc ${_libc_r} libcalendar \
libcam libcompat libdevstat libdisk libedit libfetch libform \
libftpio libgnumalloc ${_libio} libipsec libipx libisc libkvm libmenu \

View File

@ -2,39 +2,42 @@
MAINTAINER=ken@FreeBSD.ORG
LIB= cam
SRCS= camlib.c scsi_cmdparse.c scsi_all.c scsi_da.c scsi_sa.c cam.c
INCS= camlib.h
LIB= cam
SRCS= camlib.c scsi_cmdparse.c scsi_all.c scsi_da.c scsi_sa.c cam.c
INCS= camlib.h
MAN3= cam.3 cam_cdbparse.3
DPADD+= ${LIBSBUF}
LDADD+= -lsbuf
MAN3= cam.3 cam_cdbparse.3
MLINKS+=cam.3 cam_open_device.3 \
cam.3 cam_open_spec_device.3 \
cam.3 cam_open_btl.3 \
cam.3 cam_open_pass.3 \
cam.3 cam_close_device.3 \
cam.3 cam_close_spec_device.3 \
cam.3 cam_getccb.3 \
cam.3 cam_send_ccb.3 \
cam.3 cam_freeccb.3 \
cam.3 cam_path_string.3 \
cam.3 cam_device_dup.3 \
cam.3 cam_device_copy.3 \
cam.3 cam_get_device.3 \
cam_cdbparse.3 csio_build.3 \
cam_cdbparse.3 csio_build_visit.3 \
cam_cdbparse.3 csio_decode.3 \
cam_cdbparse.3 csio_decode_visit.3 \
cam_cdbparse.3 buff_decode.3 \
cam_cdbparse.3 buff_decode_visit.3 \
cam_cdbparse.3 csio_encode.3 \
cam_cdbparse.3 csio_encode_visit.3 \
cam_cdbparse.3 buff_encode_visit.3
MLINKS+= cam.3 cam_open_device.3 \
cam.3 cam_open_spec_device.3 \
cam.3 cam_open_btl.3 \
cam.3 cam_open_pass.3 \
cam.3 cam_close_device.3 \
cam.3 cam_close_spec_device.3 \
cam.3 cam_getccb.3 \
cam.3 cam_send_ccb.3 \
cam.3 cam_freeccb.3 \
cam.3 cam_path_string.3 \
cam.3 cam_device_dup.3 \
cam.3 cam_device_copy.3 \
cam.3 cam_get_device.3 \
cam_cdbparse.3 csio_build.3 \
cam_cdbparse.3 csio_build_visit.3 \
cam_cdbparse.3 csio_decode.3 \
cam_cdbparse.3 csio_decode_visit.3 \
cam_cdbparse.3 buff_decode.3 \
cam_cdbparse.3 buff_decode_visit.3 \
cam_cdbparse.3 csio_encode.3 \
cam_cdbparse.3 csio_encode_visit.3 \
cam_cdbparse.3 buff_encode_visit.3
.PATH: ${.CURDIR}/../../sys/cam/scsi ${.CURDIR}/../../sys/cam
.PATH: ${.CURDIR}/../../sys/cam/scsi ${.CURDIR}/../../sys/cam
SDIR= ${.CURDIR}/../../sys
CFLAGS+=-I${.CURDIR} -I${SDIR}
SDIR= ${.CURDIR}/../../sys
CFLAGS+= -I${.CURDIR} -I${SDIR}
.include <bsd.lib.mk>

11
lib/libsbuf/Makefile Normal file
View File

@ -0,0 +1,11 @@
# $FreeBSD$
LIB= sbuf
SRCS= subr_sbuf.c
.PATH: ${.CURDIR}/../../sys/kern
SDIR= ${.CURDIR}/../../sys
CFLAGS+=-I${SDIR}
.include <bsd.lib.mk>

View File

@ -7,7 +7,7 @@ MAN= camcontrol.8
SDIR= ${.CURDIR}/../../sys
CFLAGS+= -I${SDIR}
DPADD= ${LIBCAM}
LDADD+= -lcam
DPADD= ${LIBCAM} ${LIBSBUF}
LDADD+= -lcam -lsbuf
.include <bsd.prog.mk>

View File

@ -451,12 +451,8 @@ testunitready(struct cam_device *device, int retry_count, int timeout,
perror("error sending test unit ready");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
@ -472,12 +468,8 @@ testunitready(struct cam_device *device, int retry_count, int timeout,
error = 1;
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
}
@ -522,12 +514,8 @@ scsistart(struct cam_device *device, int startstop, int loadeject,
perror("error sending start unit");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
@ -558,12 +546,8 @@ scsistart(struct cam_device *device, int startstop, int loadeject,
"Error received from stop unit command\n");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
}
@ -702,12 +686,8 @@ scsiinquiry(struct cam_device *device, int retry_count, int timeout)
perror("error sending SCSI inquiry");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
@ -718,12 +698,8 @@ scsiinquiry(struct cam_device *device, int retry_count, int timeout)
error = 1;
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
}
@ -792,12 +768,8 @@ scsiserial(struct cam_device *device, int retry_count, int timeout)
warn("error getting serial number");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
@ -809,12 +781,8 @@ scsiserial(struct cam_device *device, int retry_count, int timeout)
error = 1;
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
}
@ -871,13 +839,9 @@ scsixferrate(struct cam_device *device)
else
warnx(error_string);
/*
* If there is an error, it won't be a SCSI error since
* this isn't a SCSI CCB.
*/
if (arglist & CAM_ARG_VERBOSE)
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
@ -1265,28 +1229,23 @@ readdefects(struct cam_device *device, int argc, char **argv,
perror("error reading defect list");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
error = 1;
goto defect_bailout;
}
if (arglist & CAM_ARG_VERBOSE)
scsi_sense_print(device, &ccb->csio, stderr);
returned_length = scsi_2btoul(((struct
scsi_read_defect_data_hdr_10 *)defect_list)->length);
returned_format = ((struct scsi_read_defect_data_hdr_10 *)
defect_list)->format;
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_SCSI_STATUS_ERROR)
&& (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
&& ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) {
struct scsi_sense_data *sense;
int error_code, sense_key, asc, ascq;
@ -1327,8 +1286,18 @@ readdefects(struct cam_device *device, int argc, char **argv,
} else {
error = 1;
warnx("Error returned from read defect data command");
if (arglist & CAM_ARG_VERBOSE)
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
goto defect_bailout;
}
} else {
error = 1;
warnx("Error returned from read defect data command");
if (arglist & CAM_ARG_VERBOSE)
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
goto defect_bailout;
}
/*
@ -1484,12 +1453,8 @@ mode_sense(struct cam_device *device, int mode_page, int page_control,
if (((retval = cam_send_ccb(device, ccb)) < 0)
|| ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
cam_close_device(device);
@ -1537,12 +1502,8 @@ mode_select(struct cam_device *device, int save_pages, int retry_count,
if (((retval = cam_send_ccb(device, ccb)) < 0)
|| ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
cam_freeccb(ccb);
cam_close_device(device);
@ -1826,12 +1787,8 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
warnx("error sending command");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
error = 1;
@ -2053,8 +2010,9 @@ tagcontrol(struct cam_device *device, int argc, char **argv,
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
warnx("XPT_REL_SIMQ CCB failed, status %#x",
ccb->ccb_h.status);
warnx("XPT_REL_SIMQ CCB failed");
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
goto tagcontrol_bailout;
}
@ -2077,8 +2035,9 @@ tagcontrol(struct cam_device *device, int argc, char **argv,
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
warnx("XPT_GDEV_STATS CCB failed, status %#x",
ccb->ccb_h.status);
warnx("XPT_GDEV_STATS CCB failed");
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
goto tagcontrol_bailout;
}
@ -2178,8 +2137,8 @@ get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
warn("get_cpi: error sending Path Inquiry CCB");
if (arglist & CAM_ARG_VERBOSE)
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
@ -2189,8 +2148,8 @@ get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (arglist & CAM_ARG_VERBOSE)
fprintf(stderr, "get_cpi: CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
@ -2367,13 +2326,18 @@ get_print_cts(struct cam_device *device, int user_settings, int quiet,
if (cam_send_ccb(device, ccb) < 0) {
perror("error sending XPT_GET_TRAN_SETTINGS CCB");
if (arglist & CAM_ARG_VERBOSE)
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
goto get_print_cts_bailout;
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
warnx("XPT_GET_TRANS_SETTINGS CCB failed, status %#x",
ccb->ccb_h.status);
warnx("XPT_GET_TRANS_SETTINGS CCB failed");
if (arglist & CAM_ARG_VERBOSE)
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
retval = 1;
goto get_print_cts_bailout;
}
@ -2497,13 +2461,20 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout,
if (cam_send_ccb(device, ccb) < 0) {
perror("error sending XPT_PATH_INQ CCB");
if (arglist & CAM_ARG_VERBOSE) {
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
retval = 1;
goto ratecontrol_bailout;
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
warnx("XPT_PATH_INQ CCB failed, status %#x",
ccb->ccb_h.status);
warnx("XPT_PATH_INQ CCB failed");
if (arglist & CAM_ARG_VERBOSE) {
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
retval = 1;
goto ratecontrol_bailout;
}
@ -2645,13 +2616,20 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout,
if (cam_send_ccb(device, ccb) < 0) {
perror("error sending XPT_SET_TRAN_SETTINGS CCB");
if (arglist & CAM_ARG_VERBOSE) {
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
retval = 1;
goto ratecontrol_bailout;
}
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
warnx("XPT_SET_TRANS_SETTINGS CCB failed, status %#x",
ccb->ccb_h.status);
warnx("XPT_SET_TRANS_SETTINGS CCB failed");
if (arglist & CAM_ARG_VERBOSE) {
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
retval = 1;
goto ratecontrol_bailout;
}
@ -2850,12 +2828,8 @@ scsiformat(struct cam_device *device, int argc, char **argv,
warnx(errstr);
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio, stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
error = 1;
goto scsiformat_bailout;
@ -2904,13 +2878,8 @@ scsiformat(struct cam_device *device, int argc, char **argv,
if (retval < 0) {
warn("error sending CAMIOCOMMAND ioctl");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
CAM_SCSI_STATUS_ERROR)
scsi_sense_print(device, &ccb->csio,
stderr);
else
fprintf(stderr, "CAM status is %#x\n",
ccb->ccb_h.status);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
}
error = 1;
goto scsiformat_bailout;
@ -2919,7 +2888,8 @@ scsiformat(struct cam_device *device, int argc, char **argv,
status = ccb->ccb_h.status & CAM_STATUS_MASK;
if ((status != CAM_REQ_CMP)
&& (status == CAM_SCSI_STATUS_ERROR)) {
&& (status == CAM_SCSI_STATUS_ERROR)
&& ((status & CAM_AUTOSNS_VALID) != 0)) {
struct scsi_sense_data *sense;
int error_code, sense_key, asc, ascq;
@ -2970,13 +2940,17 @@ scsiformat(struct cam_device *device, int argc, char **argv,
sleep(1);
} else {
warnx("Unexpected SCSI error during format");
scsi_sense_print(device, &ccb->csio, stderr);
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
error = 1;
goto scsiformat_bailout;
}
} else if (status != CAM_REQ_CMP) {
warnx("Unexpected CAM status %#x", status);
if (arglist & CAM_ARG_VERBOSE)
cam_error_print(device, ccb, CAM_ESF_ALL,
CAM_EPF_ALL, stderr);
error = 1;
goto scsiformat_bailout;
}

View File

@ -52,9 +52,9 @@
.Ft int
.Fn sbuf_setpos "struct sbuf *s" "int pos"
.Ft int
.Fn sbuf_cat "struct sbuf *s" "char *str"
.Fn sbuf_cat "struct sbuf *s" "const char *str"
.Ft int
.Fn sbuf_cpy "struct sbuf *s" "char *str"
.Fn sbuf_cpy "struct sbuf *s" "const char *str"
.Ft int
.Fn sbuf_printf "struct sbuf *s" "char *fmt" "..."
.Ft int
@ -177,7 +177,7 @@ and marks it as finished, which means that it may no longer be
modified using
.Fn sbuf_setpos ,
.Fn sbuf_cat ,
.Fn sbuf_cpu ,
.Fn sbuf_cpy ,
.Fn sbuf_printf
or
.Fn sbuf_putc .

View File

@ -80,6 +80,7 @@ LIBRADIUS?= ${DESTDIR}${LIBDIR}/libradius.a
LIBREADLINE?= ${DESTDIR}${LIBDIR}/libreadline.a
LIBRESOLV?= ${DESTDIR}${LIBDIR}/libresolv.a # XXX doesn't exist
LIBRPCSVC?= ${DESTDIR}${LIBDIR}/librpcsvc.a
LIBSBUF?= ${DESTDIR}${LIBDIR}/libsbuf.a
LIBSCRYPT?= "don't use LIBSCRYPT, use LIBCRYPT"
LIBDESCRYPT?= "don't use LIBDESCRYPT, use LIBCRYPT"
LIBSCSI?= ${DESTDIR}${LIBDIR}/libscsi.a

View File

@ -29,7 +29,71 @@
*/
#include <sys/param.h>
#ifdef _KERNEL
#include <sys/systm.h>
#else /* _KERNEL */
#include <stdlib.h>
#include <stdio.h>
#endif /* _KERNEL */
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/scsi/scsi_all.h>
#include <sys/sbuf.h>
#ifdef _KERNEL
#include <sys/libkern.h>
#include <cam/cam_xpt.h>
#endif
static int camstatusentrycomp(const void *key, const void *member);
const struct cam_status_entry cam_status_table[] = {
{ CAM_REQ_INPROG, "CCB request is in progress" },
{ CAM_REQ_CMP, "CCB request completed without error" },
{ CAM_REQ_ABORTED, "CCB request aborted by the host" },
{ CAM_UA_ABORT, "Unable to abort CCB request" },
{ CAM_REQ_CMP_ERR, "CCB request completed with an error" },
{ CAM_BUSY, "CAM subsytem is busy" },
{ CAM_REQ_INVALID, "CCB request was invalid" },
{ CAM_PATH_INVALID, "Supplied Path ID is invalid" },
{ CAM_DEV_NOT_THERE, "Device Not Present" },
{ CAM_UA_TERMIO, "Unable to terminate I/O CCB request" },
{ CAM_SEL_TIMEOUT, "Selection Timeout" },
{ CAM_CMD_TIMEOUT, "Command timeout" },
{ CAM_SCSI_STATUS_ERROR, "SCSI Status Error" },
{ CAM_MSG_REJECT_REC, "Message Reject Reveived" },
{ CAM_SCSI_BUS_RESET, "SCSI Bus Reset Sent/Received" },
{ CAM_UNCOR_PARITY, "Uncorrectable parity/CRC error" },
{ CAM_AUTOSENSE_FAIL, "Auto-Sense Retrieval Failed" },
{ CAM_NO_HBA, "No HBA Detected" },
{ CAM_DATA_RUN_ERR, "Data Overrun error" },
{ CAM_UNEXP_BUSFREE, "Unexpected Bus Free" },
{ CAM_SEQUENCE_FAIL, "Target Bus Phase Sequence Failure" },
{ CAM_CCB_LEN_ERR, "CCB length supplied is inadequate" },
{ CAM_PROVIDE_FAIL, "Unable to provide requested capability" },
{ CAM_BDR_SENT, "SCSI BDR Message Sent" },
{ CAM_REQ_TERMIO, "CCB request terminated by the host" },
{ CAM_UNREC_HBA_ERROR, "Unrecoverable Host Bus Adapter Error" },
{ CAM_REQ_TOO_BIG, "The request was too large for this host" },
{ CAM_REQUEUE_REQ, "Unconditionally Re-queue Request", },
{ CAM_IDE, "Initiator Detected Error Message Received" },
{ CAM_RESRC_UNAVAIL, "Resource Unavailable" },
{ CAM_UNACKED_EVENT, "Unacknowledged Event by Host" },
{ CAM_MESSAGE_RECV, "Message Received in Host Target Mode" },
{ CAM_INVALID_CDB, "Invalid CDB received in Host Target Mode" },
{ CAM_LUN_INVALID, "Invalid Lun" },
{ CAM_TID_INVALID, "Invalid Target ID" },
{ CAM_FUNC_NOTAVAIL, "Function Not Available" },
{ CAM_NO_NEXUS, "Nexus Not Established" },
{ CAM_IID_INVALID, "Invalid Initiator ID" },
{ CAM_CDB_RECVD, "CDB Received" },
{ CAM_LUN_ALRDY_ENA, "LUN Already Enabled for Target Mode" },
{ CAM_SCSI_BUSY, "SCSI Bus Busy" },
};
const int num_cam_status_entries =
sizeof(cam_status_table)/sizeof(*cam_status_table);
void
cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
@ -107,3 +171,183 @@ cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
}
return (NULL);
}
const struct cam_status_entry*
cam_fetch_status_entry(cam_status status)
{
status &= CAM_STATUS_MASK;
return (bsearch(&status, &cam_status_table,
num_cam_status_entries,
sizeof(*cam_status_table),
camstatusentrycomp));
}
static int
camstatusentrycomp(const void *key, const void *member)
{
cam_status status;
const struct cam_status_entry *table_entry;
status = *(const cam_status *)key;
table_entry = (const struct cam_status_entry *)member;
return (status - table_entry->status_code);
}
#ifdef _KERNEL
char *
cam_error_string(union ccb *ccb, char *str, int str_len,
cam_error_string_flags flags,
cam_error_proto_flags proto_flags)
#else /* !_KERNEL */
char *
cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
int str_len, cam_error_string_flags flags,
cam_error_proto_flags proto_flags)
#endif /* _KERNEL/!_KERNEL */
{
char path_str[64];
struct sbuf sb;
if ((ccb == NULL)
|| (str == NULL)
|| (str_len <= 0))
return(NULL);
if (flags == CAM_ESF_NONE)
return(NULL);
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
switch (proto_flags & CAM_EPF_LEVEL_MASK) {
case CAM_EPF_NONE:
break;
case CAM_EPF_ALL:
case CAM_EPF_NORMAL:
proto_flags |= CAM_ESF_PRINT_SENSE;
/* FALLTHROUGH */
case CAM_EPF_MINIMAL:
proto_flags |= CAM_ESF_PRINT_STATUS;
default:
break;
}
break;
default:
break;
}
#ifdef _KERNEL
xpt_path_string(ccb->csio.ccb_h.path, path_str, sizeof(path_str));
#else /* !_KERNEL */
cam_path_string(device, path_str, sizeof(path_str));
#endif /* _KERNEL/!_KERNEL */
sbuf_new(&sb, str, str_len, 0);
if (flags & CAM_ESF_COMMAND) {
sbuf_cat(&sb, path_str);
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
#ifdef _KERNEL
scsi_command_string(&ccb->csio, &sb);
#else /* !_KERNEL */
scsi_command_string(device, &ccb->csio, &sb);
#endif /* _KERNEL/!_KERNEL */
sbuf_printf(&sb, "\n");
break;
default:
break;
}
}
if (flags & CAM_ESF_CAM_STATUS) {
cam_status status;
const struct cam_status_entry *entry;
sbuf_cat(&sb, path_str);
status = ccb->ccb_h.status & CAM_STATUS_MASK;
entry = cam_fetch_status_entry(status);
if (entry == NULL)
sbuf_printf(&sb, "CAM Status: Unknown (%#x)\n",
ccb->ccb_h.status);
else
sbuf_printf(&sb, "CAM Status: %s\n",
entry->status_text);
}
if (flags & CAM_ESF_PROTO_STATUS) {
switch (ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
if ((ccb->ccb_h.status & CAM_STATUS_MASK) !=
CAM_SCSI_STATUS_ERROR)
break;
if (proto_flags & CAM_ESF_PRINT_STATUS) {
sbuf_cat(&sb, path_str);
/*
* Print out the SCSI status byte as long as
* the user wants some protocol output.
*/
sbuf_printf(&sb, "SCSI Status: %s\n",
scsi_status_string(&ccb->csio));
}
if ((proto_flags & CAM_ESF_PRINT_SENSE)
&& (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND)
&& (ccb->ccb_h.status & CAM_AUTOSNS_VALID)) {
#ifdef _KERNEL
scsi_sense_sbuf(&ccb->csio, &sb,
SSS_FLAG_NONE);
#else /* !_KERNEL */
scsi_sense_sbuf(device, &ccb->csio, &sb,
SSS_FLAG_NONE);
#endif /* _KERNEL/!_KERNEL */
}
break;
default:
break;
}
}
sbuf_finish(&sb);
return(sbuf_data(&sb));
}
#ifdef _KERNEL
void
cam_error_print(union ccb *ccb, cam_error_string_flags flags,
cam_error_proto_flags proto_flags)
{
char str[512];
printf("%s", cam_error_string(ccb, str, sizeof(str), flags,
proto_flags));
}
#else /* !_KERNEL */
void
cam_error_print(struct cam_device *device, union ccb *ccb,
cam_error_string_flags flags, cam_error_proto_flags proto_flags,
FILE *ofile)
{
char str[512];
if ((device == NULL) || (ccb == NULL) || (ofile == NULL))
return;
fprintf(ofile, "%s", cam_error_string(device, ccb, str, sizeof(str),
flags, proto_flags));
}
#endif /* _KERNEL/!_KERNEL */

View File

@ -85,10 +85,11 @@ typedef struct {
*/
#define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0)
/* CAM flags */
/* CAM flags XXX Move to cam_periph.h ??? */
typedef enum {
CAM_FLAG_NONE = 0x00,
CAM_EXPECT_INQ_CHANGE = 0x01
CAM_EXPECT_INQ_CHANGE = 0x01,
CAM_RETRY_SELTO = 0x02 /* Retry Selection Timeouts */
} cam_flags;
/* CAM Status field values */
@ -139,7 +140,7 @@ typedef enum {
CAM_NO_NEXUS, /* Nexus is not established */
CAM_IID_INVALID, /* The initiator ID is invalid */
CAM_CDB_RECVD, /* The SCSI CDB has been received */
CAM_LUN_ALRDY_ENA, /* The LUN is already eanbeld for target mode */
CAM_LUN_ALRDY_ENA, /* The LUN is already enabled for target mode */
CAM_SCSI_BUSY, /* SCSI Bus Busy */
CAM_DEV_QFRZN = 0x40, /* The DEV queue is frozen w/this err */
@ -155,6 +156,39 @@ typedef enum {
CAM_SENT_SENSE = 0x40000000 /* sent sense with status */
} cam_status;
typedef enum {
CAM_ESF_NONE = 0x00,
CAM_ESF_COMMAND = 0x01,
CAM_ESF_CAM_STATUS = 0x02,
CAM_ESF_PROTO_STATUS = 0x04,
CAM_ESF_ALL = 0xff
} cam_error_string_flags;
typedef enum {
CAM_EPF_NONE = 0x00,
CAM_EPF_MINIMAL = 0x01,
CAM_EPF_NORMAL = 0x02,
CAM_EPF_ALL = 0x03,
CAM_EPF_LEVEL_MASK = 0x0f
/* All bits above bit 3 are protocol-specific */
} cam_error_proto_flags;
typedef enum {
CAM_ESF_PRINT_NONE = 0x00,
CAM_ESF_PRINT_STATUS = 0x10,
CAM_ESF_PRINT_SENSE = 0x20
} cam_error_scsi_flags;
struct cam_status_entry
{
cam_status status_code;
const char *status_text;
};
extern const struct cam_status_entry cam_status_table[];
extern const int num_cam_status_entries;
union ccb;
__BEGIN_DECLS
typedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
@ -164,6 +198,24 @@ caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
int cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
const struct cam_status_entry*
cam_fetch_status_entry(cam_status status);
#ifdef _KERNEL
char * cam_error_string(union ccb *ccb, char *str, int str_len,
cam_error_string_flags flags,
cam_error_proto_flags proto_flags);
void cam_error_print(union ccb *ccb, cam_error_string_flags flags,
cam_error_proto_flags proto_flags);
#else /* _KERNEL */
struct cam_device;
char * cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
int str_len, cam_error_string_flags flags,
cam_error_proto_flags proto_flags);
void cam_error_print(struct cam_device *device, union ccb *ccb,
cam_error_string_flags flags,
cam_error_proto_flags proto_flags, FILE *ofile);
#endif /* _KERNEL */
__END_DECLS
#ifdef _KERNEL

View File

@ -34,6 +34,9 @@
#include <sys/queue.h>
#include <sys/cdefs.h>
#include <sys/time.h>
#ifdef CAM_NEW_TRAN_CODE
#include <machine/limits.h>
#endif /* CAM_NEW_TRAN_CODE */
#ifndef _KERNEL
#include <sys/callout.h>
#endif
@ -172,7 +175,7 @@ typedef enum {
/* HBA engine commands 0x20->0x2F */
XPT_ENG_INQ = 0x20 | XPT_FC_XPT_ONLY,
/* HBA engine feature inquiry */
XPT_ENG_EXEC = 0x21 | XPT_FC_DEV_QUEUED | XPT_FC_XPT_ONLY,
XPT_ENG_EXEC = 0x21 | XPT_FC_DEV_QUEUED,
/* HBA execute engine request */
/* Target mode commands: 0x30->0x3F */
@ -205,6 +208,33 @@ typedef enum {
(((ccb)->ccb_h.func_code & XPT_FC_DEV_QUEUED) == XPT_FC_DEV_QUEUED)
#define XPT_FC_IS_QUEUED(ccb) \
(((ccb)->ccb_h.func_code & XPT_FC_QUEUED) != 0)
#ifdef CAM_NEW_TRAN_CODE
typedef enum {
PROTO_UNKNOWN,
PROTO_UNSPECIFIED,
PROTO_SCSI, /* Small Computer System Interface */
PROTO_ATA, /* AT Attachment */
PROTO_ATAPI, /* AT Attachment Packetized Interface */
} cam_proto;
typedef enum {
XPORT_UNKNOWN,
XPORT_UNSPECIFIED,
XPORT_SPI, /* SCSI Parallel Interface */
XPORT_FC, /* Fiber Channel */
XPORT_SSA, /* Serial Storage Architecture */
XPORT_USB, /* Universal Serial Bus */
XPORT_PPB, /* Parallel Port Bus */
XPORT_ATA /* AT Attachment */
} cam_xport;
#define PROTO_VERSION_UNKNOWN (UINT_MAX - 1)
#define PROTO_VERSION_UNSPECIFIED UINT_MAX
#define XPORT_VERSION_UNKNOWN (UINT_MAX - 1)
#define XPORT_VERSION_UNSPECIFIED UINT_MAX
#endif /* CAM_NEW_TRAN_CODE */
typedef union {
LIST_ENTRY(ccb_hdr) le;
SLIST_ENTRY(ccb_hdr) sle;
@ -257,7 +287,7 @@ struct ccb_getdev {
struct ccb_hdr ccb_h;
struct scsi_inquiry_data inq_data;
u_int8_t serial_num[252];
u_int8_t inq_len;
u_int8_t reserved;
u_int8_t serial_num_len;
};
@ -486,7 +516,13 @@ typedef enum {
PIM_NOBUSRESET = 0x10 /* User has disabled initial BUS RESET */
} pi_miscflag;
#ifdef CAM_NEW_TRAN_CODE
/* Path Inquiry CCB */
struct ccb_pathinq_settings_spi {
u_int8_t ppr_options;
};
#endif /* CAM_NEW_TRAN_CODE */
struct ccb_pathinq {
struct ccb_hdr ccb_h;
u_int8_t version_num; /* Version number for the SIM/HBA */
@ -507,6 +543,15 @@ struct ccb_pathinq {
u_int32_t unit_number; /* Unit number for SIM */
u_int32_t bus_id; /* Bus ID for SIM */
u_int32_t base_transfer_speed;/* Base bus speed in KB/sec */
#ifdef CAM_NEW_TRAN_CODE
cam_proto protocol;
u_int protocol_version;
cam_xport transport;
u_int transport_version;
union {
struct ccb_pathinq_settings_spi spi;
} xport_specific;
#endif /* CAM_NEW_TRAN_CODE */
};
/* Path Statistics CCB */
@ -644,25 +689,77 @@ struct ccb_termio {
union ccb *termio_ccb; /* Pointer to CCB to terminate */
};
#ifndef CAM_NEW_TRAN_CODE
/* Get/Set transfer rate/width/disconnection/tag queueing settings */
struct ccb_trans_settings {
struct ccb_hdr ccb_h;
u_int valid; /* Which fields to honor */
#define CCB_TRANS_SYNC_RATE_VALID 0x01
#define CCB_TRANS_SYNC_OFFSET_VALID 0x02
#define CCB_TRANS_BUS_WIDTH_VALID 0x04
#define CCB_TRANS_DISC_VALID 0x08
#define CCB_TRANS_TQ_VALID 0x10
u_int valid; /* Which fields to honor */
#define CCB_TRANS_SYNC_RATE_VALID 0x01
#define CCB_TRANS_SYNC_OFFSET_VALID 0x02
#define CCB_TRANS_BUS_WIDTH_VALID 0x04
#define CCB_TRANS_DISC_VALID 0x08
#define CCB_TRANS_TQ_VALID 0x10
u_int flags;
#define CCB_TRANS_CURRENT_SETTINGS 0x01
#define CCB_TRANS_USER_SETTINGS 0x02
#define CCB_TRANS_DISC_ENB 0x04
#define CCB_TRANS_TAG_ENB 0x08
#define CCB_TRANS_CURRENT_SETTINGS 0x01
#define CCB_TRANS_USER_SETTINGS 0x02
#define CCB_TRANS_DISC_ENB 0x04
#define CCB_TRANS_TAG_ENB 0x08
u_int sync_period;
u_int sync_offset;
u_int bus_width;
};
#else /* CAM_NEW_TRAN_CODE */
typedef enum {
CTS_TYPE_CURRENT_SETTINGS,
CTS_TYPE_USER_SETTINGS
} cts_type;
struct ccb_trans_settings_scsi
{
u_int valid; /* Which fields to honor */
#define CTS_SCSI_VALID_TQ 0x01
u_int flags;
#define CTS_SCSI_FLAGS_TAG_ENB 0x01
};
struct ccb_trans_settings_spi
{
u_int valid; /* Which fields to honor */
#define CTS_SPI_VALID_SYNC_RATE 0x01
#define CTS_SPI_VALID_SYNC_OFFSET 0x02
#define CTS_SPI_VALID_BUS_WIDTH 0x04
#define CTS_SPI_VALID_DISC 0x08
#define CTS_SPI_VALID_PPR_OPTIONS 0x10
u_int flags;
#define CTS_SPI_FLAGS_DISC_ENB 0x01
#define CTS_SPI_FLAGS_TAG_ENB 0x02
u_int sync_period;
u_int sync_offset;
u_int bus_width;
u_int ppr_options;
};
/* Get/Set transfer rate/width/disconnection/tag queueing settings */
struct ccb_trans_settings {
struct ccb_hdr ccb_h;
cts_type type; /* Current or User settings */
cam_proto protocol;
u_int protocol_version;
cam_xport transport;
u_int transport_version;
union {
u_int valid; /* Which fields to honor */
struct ccb_trans_settings_scsi scsi;
} proto_specific;
union {
u_int valid; /* Which fields to honor */
struct ccb_trans_settings_spi spi;
} xport_specific;
};
#endif /* CAM_NEW_TRAN_CODE */
/*
* Calculate the geometry parameters for a device
* give the block size and volume size in blocks.

View File

@ -53,7 +53,7 @@ typedef enum {
extern struct cam_path *cam_dpath;
/* Current debug levels set */
extern u_int32_t cam_dflags;
/* Printf delay value (to prevent scrolling */
/* Printf delay value (to prevent scrolling) */
extern u_int32_t cam_debug_delay;
/* Debugging macros. */

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@
#include <sys/md5.h>
#include <sys/devicestat.h>
#include <sys/interrupt.h>
#include <sys/sbuf.h>
#ifdef PC98
#include <pc98/pc98/pc98_machdep.h> /* geometry translation */
@ -122,7 +123,13 @@ struct cam_ed {
struct cam_periph *owner; /* Peripheral driver's ownership tag */
struct xpt_quirk_entry *quirk; /* Oddities about this device */
/* Storage for the inquiry data */
struct scsi_inquiry_data inq_data;
#ifdef CAM_NEW_TRAN_CODE
cam_proto protocol;
u_int protocol_version;
cam_xport transport;
u_int transport_version;
#endif /* CAM_NEW_TRAN_CODE */
struct scsi_inquiry_data inq_data;
u_int8_t inq_flags; /*
* Current settings for inquiry flags.
* This allows us to override settings
@ -131,7 +138,7 @@ struct cam_ed {
*/
u_int8_t queue_flags; /* Queue flags from the control page */
u_int8_t serial_num_len;
u_int8_t *serial_num;
u_int8_t *serial_num;
u_int32_t qfrozen_cnt;
u_int32_t flags;
#define CAM_DEV_UNCONFIGURED 0x01
@ -718,11 +725,12 @@ static void xptasync(struct cam_periph *periph,
u_int32_t code, cam_path *path);
#endif
static dev_match_ret xptbusmatch(struct dev_match_pattern *patterns,
int num_patterns, struct cam_eb *bus);
u_int num_patterns, struct cam_eb *bus);
static dev_match_ret xptdevicematch(struct dev_match_pattern *patterns,
int num_patterns, struct cam_ed *device);
u_int num_patterns,
struct cam_ed *device);
static dev_match_ret xptperiphmatch(struct dev_match_pattern *patterns,
int num_patterns,
u_int num_patterns,
struct cam_periph *periph);
static xpt_busfunc_t xptedtbusfunc;
static xpt_targetfunc_t xptedttargetfunc;
@ -776,6 +784,9 @@ static void proberequestdefaultnegotiation(struct cam_periph *periph);
static void probedone(struct cam_periph *periph, union ccb *done_ccb);
static void probecleanup(struct cam_periph *periph);
static void xpt_find_quirk(struct cam_ed *device);
#ifdef CAM_NEW_TRAN_CODE
static void xpt_devise_transport(struct cam_path *path);
#endif /* CAM_NEW_TRAN_CODE */
static void xpt_set_transfer_settings(struct ccb_trans_settings *cts,
struct cam_ed *device,
int async_update);
@ -1129,8 +1140,8 @@ xptioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
struct cam_periph *periph;
struct periph_driver **p_drv;
char *name;
int unit;
int cur_generation;
u_int unit;
u_int cur_generation;
int base_periph_found;
int splbreaknum;
int s;
@ -1464,6 +1475,118 @@ xpt_remove_periph(struct cam_periph *periph)
}
#ifdef CAM_NEW_TRAN_CODE
void
xpt_announce_periph(struct cam_periph *periph, char *announce_string)
{
struct ccb_pathinq cpi;
struct ccb_trans_settings cts;
struct cam_path *path;
u_int speed;
u_int freq;
u_int mb;
int s;
path = periph->path;
/*
* To ensure that this is printed in one piece,
* mask out CAM interrupts.
*/
s = splsoftcam();
printf("%s%d at %s%d bus %d target %d lun %d\n",
periph->periph_name, periph->unit_number,
path->bus->sim->sim_name,
path->bus->sim->unit_number,
path->bus->sim->bus_id,
path->target->target_id,
path->device->lun_id);
printf("%s%d: ", periph->periph_name, periph->unit_number);
scsi_print_inquiry(&path->device->inq_data);
if ((bootverbose)
&& (path->device->serial_num_len > 0)) {
/* Don't wrap the screen - print only the first 60 chars */
printf("%s%d: Serial Number %.60s\n", periph->periph_name,
periph->unit_number, path->device->serial_num);
}
xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
xpt_action((union ccb*)&cts);
/* Ask the SIM for its base transfer speed */
xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
speed = cpi.base_transfer_speed;
freq = 0;
if (cts.ccb_h.status == CAM_REQ_CMP
&& cts.transport == XPORT_SPI) {
struct ccb_trans_settings_spi *spi;
spi = &cts.xport_specific.spi;
if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0
&& spi->sync_offset != 0) {
freq = scsi_calc_syncsrate(spi->sync_period);
speed = freq;
}
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
speed *= (0x01 << spi->bus_width);
}
mb = speed / 1000;
if (mb > 0)
printf("%s%d: %d.%03dMB/s transfers",
periph->periph_name, periph->unit_number,
mb, speed % 1000);
else
printf("%s%d: %dKB/s transfers", periph->periph_name,
periph->unit_number, speed);
/* Report additional information about SPI connections */
if (cts.ccb_h.status == CAM_REQ_CMP
&& cts.transport == XPORT_SPI) {
struct ccb_trans_settings_spi *spi;
spi = &cts.xport_specific.spi;
if (freq != 0) {
printf(" (%d.%03dMHz%s, offset %d", freq / 1000,
freq % 1000,
(spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
? " DT" : "",
spi->sync_offset);
}
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0
&& spi->bus_width > 0) {
if (freq != 0) {
printf(", ");
} else {
printf(" (");
}
printf("%dbit)", 8 * (0x01 << spi->bus_width));
} else if (freq != 0) {
printf(")");
}
}
if (path->device->inq_flags & SID_CmdQue
|| path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
printf("\n%s%d: Tagged Queueing Enabled",
periph->periph_name, periph->unit_number);
}
printf("\n");
/*
* We only want to print the caller's announce string if they've
* passed one in..
*/
if (announce_string != NULL)
printf("%s%d: %s\n", periph->periph_name,
periph->unit_number, announce_string);
splx(s);
}
#else /* CAM_NEW_TRAN_CODE */
void
xpt_announce_periph(struct cam_periph *periph, char *announce_string)
{
@ -1567,9 +1690,10 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
splx(s);
}
#endif /* CAM_NEW_TRAN_CODE */
static dev_match_ret
xptbusmatch(struct dev_match_pattern *patterns, int num_patterns,
xptbusmatch(struct dev_match_pattern *patterns, u_int num_patterns,
struct cam_eb *bus)
{
dev_match_ret retval;
@ -1681,7 +1805,7 @@ xptbusmatch(struct dev_match_pattern *patterns, int num_patterns,
}
static dev_match_ret
xptdevicematch(struct dev_match_pattern *patterns, int num_patterns,
xptdevicematch(struct dev_match_pattern *patterns, u_int num_patterns,
struct cam_ed *device)
{
dev_match_ret retval;
@ -1797,7 +1921,7 @@ xptdevicematch(struct dev_match_pattern *patterns, int num_patterns,
* Match a single peripheral against any number of match patterns.
*/
static dev_match_ret
xptperiphmatch(struct dev_match_pattern *patterns, int num_patterns,
xptperiphmatch(struct dev_match_pattern *patterns, u_int num_patterns,
struct cam_periph *periph)
{
dev_match_ret retval;
@ -2778,6 +2902,9 @@ xpt_action(union ccb *start_ccb)
switch (start_ccb->ccb_h.func_code) {
case XPT_SCSI_IO:
{
#ifdef CAM_NEW_TRAN_CODE
struct cam_ed *device;
#endif /* CAM_NEW_TRAN_CODE */
#ifdef CAMDEBUG
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
struct cam_path *path;
@ -2801,7 +2928,12 @@ xpt_action(union ccb *start_ccb)
* This means that this code will be exercised while probing
* devices with an ANSI revision greater than 2.
*/
#ifdef CAM_NEW_TRAN_CODE
device = start_ccb->ccb_h.path->device;
if (device->protocol_version <= SCSI_REV_2
#else /* CAM_NEW_TRAN_CODE */
if (SID_ANSI_REV(&start_ccb->ccb_h.path->device->inq_data) <= 2
#endif /* CAM_NEW_TRAN_CODE */
&& start_ccb->ccb_h.target_lun < 8
&& (start_ccb->ccb_h.flags & CAM_CDB_POINTER) == 0) {
@ -3023,7 +3155,7 @@ xpt_action(union ccb *start_ccb)
struct cam_periph *nperiph;
struct periph_list *periph_head;
struct ccb_getdevlist *cgdl;
int i;
u_int i;
int s;
struct cam_ed *device;
int found;
@ -3115,7 +3247,7 @@ xpt_action(union ccb *start_ccb)
if (cdm->pos.position_type != CAM_DEV_POS_NONE)
position_type = cdm->pos.position_type;
else {
int i;
u_int i;
position_type = CAM_DEV_POS_NONE;
@ -3980,6 +4112,44 @@ xpt_print_path(struct cam_path *path)
}
}
int
xpt_path_string(struct cam_path *path, char *str, size_t str_len)
{
struct sbuf sb;
sbuf_new(&sb, str, str_len, 0);
if (path == NULL)
sbuf_printf(&sb, "(nopath): ");
else {
if (path->periph != NULL)
sbuf_printf(&sb, "(%s%d:", path->periph->periph_name,
path->periph->unit_number);
else
sbuf_printf(&sb, "(noperiph:");
if (path->bus != NULL)
sbuf_printf(&sb, "%s%d:%d:", path->bus->sim->sim_name,
path->bus->sim->unit_number,
path->bus->sim->bus_id);
else
sbuf_printf(&sb, "nobus:");
if (path->target != NULL)
sbuf_printf(&sb, "%d:", path->target->target_id);
else
sbuf_printf(&sb, "X:");
if (path->device != NULL)
sbuf_printf(&sb, "%d): ", path->device->lun_id);
else
sbuf_printf(&sb, "X): ");
}
sbuf_finish(&sb);
return(sbuf_len(&sb));
}
path_id_t
xpt_path_path_id(struct cam_path *path)
{
@ -4115,7 +4285,7 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus)
xpt_setup_ccb(&cpi.ccb_h, &path, /*priority*/1);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
xpt_async(AC_PATH_REGISTERED, xpt_periph->path, &cpi);
xpt_async(AC_PATH_REGISTERED, &path, &cpi);
xpt_release_path(&path);
}
return (CAM_SUCCESS);
@ -4693,6 +4863,9 @@ xpt_release_target(struct cam_eb *bus, struct cam_et *target)
static struct cam_ed *
xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
{
#ifdef CAM_NEW_TRAN_CODE
struct cam_path path;
#endif /* CAM_NEW_TRAN_CODE */
struct cam_ed *device;
struct cam_devq *devq;
cam_status status;
@ -4769,6 +4942,17 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id)
TAILQ_INSERT_TAIL(&target->ed_entries, device, links);
}
target->generation++;
#ifdef CAM_NEW_TRAN_CODE
if (lun_id != CAM_LUN_WILDCARD) {
xpt_compile_path(&path,
NULL,
bus->path_id,
target->target_id,
lun_id);
xpt_devise_transport(&path);
xpt_release_path(&path);
}
#endif /* CAM_NEW_TRAN_CODE */
}
return (device);
}
@ -4964,10 +5148,6 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
work_ccb->ccb_h.cbfcnp = xpt_scan_bus;
work_ccb->ccb_h.ppriv_ptr0 = scan_info;
work_ccb->crcn.flags = request_ccb->crcn.flags;
#if 0
printf("xpt_scan_bus: probing %d:%d:%d\n",
request_ccb->ccb_h.path_id, i, 0);
#endif
xpt_action(work_ccb);
}
break;
@ -4990,11 +5170,6 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
lun_id = request_ccb->ccb_h.target_lun;
xpt_action(request_ccb);
#if 0
printf("xpt_scan_bus: got back probe from %d:%d:%d\n",
path_id, target_id, lun_id);
#endif
if (request_ccb->ccb_h.status != CAM_REQ_CMP) {
struct cam_ed *device;
struct cam_et *target;
@ -5087,10 +5262,6 @@ xpt_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
request_ccb->ccb_h.ppriv_ptr0 = scan_info;
request_ccb->crcn.flags =
scan_info->request_ccb->crcn.flags;
#if 0
xpt_print_path(path);
printf("xpt_scan bus probing\n");
#endif
xpt_action(request_ccb);
}
break;
@ -5468,11 +5639,19 @@ proberequestdefaultnegotiation(struct cam_periph *periph)
xpt_setup_ccb(&cts.ccb_h, periph->path, /*priority*/1);
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_USER_SETTINGS;
#else /* CAM_NEW_TRAN_CODE */
cts.flags = CCB_TRANS_USER_SETTINGS;
#endif /* CAM_NEW_TRAN_CODE */
xpt_action((union ccb *)&cts);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
#ifdef CAM_NEW_TRAN_CODE
cts.type = CTS_TYPE_CURRENT_SETTINGS;
#else /* CAM_NEW_TRAN_CODE */
cts.flags &= ~CCB_TRANS_USER_SETTINGS;
cts.flags |= CCB_TRANS_CURRENT_SETTINGS;
#endif /* CAM_NEW_TRAN_CODE */
xpt_action((union ccb *)&cts);
}
@ -5550,6 +5729,9 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
xpt_find_quirk(path->device);
#ifdef CAM_NEW_TRAN_CODE
xpt_devise_transport(path);
#endif /* CAM_NEW_TRAN_CODE */
if ((inq_buf->flags & SID_CmdQue) != 0)
softc->action =
PROBE_MODE_SENSE;
@ -5788,6 +5970,379 @@ xpt_find_quirk(struct cam_ed *device)
device->quirk = (struct xpt_quirk_entry *)match;
}
#ifdef CAM_NEW_TRAN_CODE
static void
xpt_devise_transport(struct cam_path *path)
{
struct ccb_pathinq cpi;
struct ccb_trans_settings cts;
struct scsi_inquiry_data *inq_buf;
/* Get transport information from the SIM */
xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
inq_buf = NULL;
if ((path->device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0)
inq_buf = &path->device->inq_data;
path->device->protocol = PROTO_SCSI;
path->device->protocol_version =
inq_buf != NULL ? SID_ANSI_REV(inq_buf) : cpi.protocol_version;
path->device->transport = cpi.transport;
path->device->transport_version = cpi.transport_version;
/*
* Any device not using SPI3 features should
* be considered SPI2 or lower.
*/
if (inq_buf != NULL) {
if (path->device->transport == XPORT_SPI
&& (inq_buf->spi3data & SID_SPI_MASK) == 0
&& path->device->transport_version > 2)
path->device->transport_version = 2;
} else {
struct cam_ed* otherdev;
for (otherdev = TAILQ_FIRST(&path->target->ed_entries);
otherdev != NULL;
otherdev = TAILQ_NEXT(otherdev, links)) {
if (otherdev != path->device)
break;
}
if (otherdev != NULL) {
/*
* Initially assume the same versioning as
* prior luns for this target.
*/
path->device->protocol_version =
otherdev->protocol_version;
path->device->transport_version =
otherdev->transport_version;
} else {
/* Until we know better, opt for safty */
path->device->protocol_version = 2;
if (path->device->transport == XPORT_SPI)
path->device->transport_version = 2;
else
path->device->transport_version = 0;
}
}
/*
* XXX
* For a device compliant with SPC-2 we should be able
* to determine the transport version supported by
* scrutinizing the version descriptors in the
* inquiry buffer.
*/
/* Tell the controller what we think */
xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1);
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
cts.type = CTS_TYPE_CURRENT_SETTINGS;
cts.transport = path->device->transport;
cts.transport_version = path->device->transport_version;
cts.protocol = path->device->protocol;
cts.protocol_version = path->device->protocol_version;
cts.proto_specific.valid = 0;
cts.xport_specific.valid = 0;
xpt_action((union ccb *)&cts);
}
static void
xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
int async_update)
{
struct ccb_pathinq cpi;
struct ccb_trans_settings cur_cts;
struct ccb_trans_settings_scsi *scsi;
struct ccb_trans_settings_scsi *cur_scsi;
struct cam_sim *sim;
struct scsi_inquiry_data *inq_data;
if (device == NULL) {
cts->ccb_h.status = CAM_PATH_INVALID;
xpt_done((union ccb *)cts);
return;
}
if (cts->protocol == PROTO_UNKNOWN
|| cts->protocol == PROTO_UNSPECIFIED) {
cts->protocol = device->protocol;
cts->protocol_version = device->protocol_version;
}
if (cts->protocol_version == PROTO_VERSION_UNKNOWN
|| cts->protocol_version == PROTO_VERSION_UNSPECIFIED)
cts->protocol_version = device->protocol_version;
if (cts->protocol != device->protocol) {
xpt_print_path(cts->ccb_h.path);
printf("Uninitialized Protocol %x:%x?\n",
cts->protocol, device->protocol);
cts->protocol = device->protocol;
}
if (cts->protocol_version > device->protocol_version) {
if (bootverbose) {
xpt_print_path(cts->ccb_h.path);
printf("Down reving Protocol Version from %d to %d?\n",
cts->protocol_version, device->protocol_version);
}
cts->protocol_version = device->protocol_version;
}
if (cts->transport == XPORT_UNKNOWN
|| cts->transport == XPORT_UNSPECIFIED) {
cts->transport = device->transport;
cts->transport_version = device->transport_version;
}
if (cts->transport_version == XPORT_VERSION_UNKNOWN
|| cts->transport_version == XPORT_VERSION_UNSPECIFIED)
cts->transport_version = device->transport_version;
if (cts->transport != device->transport) {
xpt_print_path(cts->ccb_h.path);
printf("Uninitialized Transport %x:%x?\n",
cts->transport, device->transport);
cts->transport = device->transport;
}
if (cts->transport_version > device->transport_version) {
if (bootverbose) {
xpt_print_path(cts->ccb_h.path);
printf("Down reving Transport Version from %d to %d?\n",
cts->transport_version,
device->transport_version);
}
cts->transport_version = device->transport_version;
}
sim = cts->ccb_h.path->bus->sim;
/*
* Nothing more of interest to do unless
* this is a device connected via the
* SCSI protocol.
*/
if (cts->protocol != PROTO_SCSI) {
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
return;
}
inq_data = &device->inq_data;
scsi = &cts->proto_specific.scsi;
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
/* SCSI specific sanity checking */
if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0
|| (inq_data->flags & SID_CmdQue) == 0
|| (device->queue_flags & SCP_QUEUE_DQUE) != 0
|| (device->quirk->mintags == 0)) {
/*
* Can't tag on hardware that doesn't support tags,
* doesn't have it enabled, or has broken tag support.
*/
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
}
if (async_update == FALSE) {
/*
* Perform sanity checking against what the
* controller and device can do.
*/
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1);
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
cur_cts.type = cts->type;
xpt_action((union ccb *)&cur_cts);
cur_scsi = &cur_cts.proto_specific.scsi;
if ((scsi->valid & CTS_SCSI_VALID_TQ) == 0) {
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
scsi->flags |= cur_scsi->flags & CTS_SCSI_FLAGS_TAG_ENB;
}
if ((cur_scsi->valid & CTS_SCSI_VALID_TQ) == 0)
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
}
/* SPI specific sanity checking */
if (cts->transport == XPORT_SPI
&& async_update == FALSE) {
u_int spi3caps;
struct ccb_trans_settings_spi *spi;
struct ccb_trans_settings_spi *cur_spi;
spi = &cts->xport_specific.spi;
cur_spi = &cur_cts.xport_specific.spi;
/* Fill in any gaps in what the user gave us */
if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
spi->sync_period = cur_spi->sync_period;
if ((cur_spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
spi->sync_period = 0;
if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
spi->sync_offset = cur_spi->sync_offset;
if ((cur_spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
spi->sync_offset = 0;
if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
spi->ppr_options = cur_spi->ppr_options;
if ((cur_spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0)
spi->ppr_options = 0;
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
spi->bus_width = cur_spi->bus_width;
if ((cur_spi->valid & CTS_SPI_VALID_BUS_WIDTH) == 0)
spi->bus_width = 0;
if ((spi->valid & CTS_SPI_VALID_DISC) == 0) {
spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
spi->flags |= cur_spi->flags & CTS_SPI_FLAGS_DISC_ENB;
}
if ((cur_spi->valid & CTS_SPI_VALID_DISC) == 0)
spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
&& (inq_data->flags & SID_Sync) == 0
&& cts->type == CTS_TYPE_CURRENT_SETTINGS)
|| ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0)
|| (cts->sync_offset == 0)
|| (cts->sync_period == 0)) {
/* Force async */
spi->sync_period = 0;
spi->sync_offset = 0;
}
switch (spi->bus_width) {
case MSG_EXT_WDTR_BUS_32_BIT:
if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
|| (inq_data->flags & SID_WBus32) != 0
|| cts->type == CTS_TYPE_USER_SETTINGS)
&& (cpi.hba_inquiry & PI_WIDE_32) != 0)
break;
/* Fall Through to 16-bit */
case MSG_EXT_WDTR_BUS_16_BIT:
if (((device->flags & CAM_DEV_INQUIRY_DATA_VALID) == 0
|| (inq_data->flags & SID_WBus16) != 0
|| cts->type == CTS_TYPE_USER_SETTINGS)
&& (cpi.hba_inquiry & PI_WIDE_16) != 0) {
spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
break;
}
/* Fall Through to 8-bit */
default: /* New bus width?? */
case MSG_EXT_WDTR_BUS_8_BIT:
/* All targets can do this */
spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
break;
}
spi3caps = cpi.xport_specific.spi.ppr_options;
if ((device->flags & CAM_DEV_INQUIRY_DATA_VALID) != 0
&& cts->type == CTS_TYPE_CURRENT_SETTINGS)
spi3caps &= inq_data->spi3data;
if ((spi3caps & SID_SPI_CLOCK_DT) == 0)
spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
if ((spi3caps & SID_SPI_IUS) == 0)
spi->ppr_options &= ~MSG_EXT_PPR_IU_REQ;
if ((spi3caps & SID_SPI_QAS) == 0)
spi->ppr_options &= ~MSG_EXT_PPR_QAS_REQ;
/* No SPI Transfer settings are allowed unless we are wide */
if (spi->bus_width == 0)
spi->ppr_options = 0;
if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) == 0) {
/*
* Can't tag queue without disconnection.
*/
scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
scsi->valid |= CTS_SCSI_VALID_TQ;
}
/*
* If we are currently performing tagged transactions to
* this device and want to change its negotiation parameters,
* go non-tagged for a bit to give the controller a chance to
* negotiate unhampered by tag messages.
*/
if (cts->type == CTS_TYPE_CURRENT_SETTINGS
&& (device->inq_flags & SID_CmdQue) != 0
&& (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
&& (spi->flags & (CTS_SPI_VALID_SYNC_RATE|
CTS_SPI_VALID_SYNC_OFFSET|
CTS_SPI_VALID_BUS_WIDTH)) != 0)
xpt_toggle_tags(cts->ccb_h.path);
}
if (cts->type == CTS_TYPE_CURRENT_SETTINGS
&& (scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
int device_tagenb;
/*
* If we are transitioning from tags to no-tags or
* vice-versa, we need to carefully freeze and restart
* the queue so that we don't overlap tagged and non-tagged
* commands. We also temporarily stop tags if there is
* a change in transfer negotiation settings to allow
* "tag-less" negotiation.
*/
if ((device->flags & CAM_DEV_TAG_AFTER_COUNT) != 0
|| (device->inq_flags & SID_CmdQue) != 0)
device_tagenb = TRUE;
else
device_tagenb = FALSE;
if (((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0
&& device_tagenb == FALSE)
|| ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) == 0
&& device_tagenb == TRUE)) {
if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
/*
* Delay change to use tags until after a
* few commands have gone to this device so
* the controller has time to perform transfer
* negotiations without tagged messages getting
* in the way.
*/
device->tag_delay_count = CAM_TAG_DELAY_COUNT;
device->flags |= CAM_DEV_TAG_AFTER_COUNT;
} else {
struct ccb_relsim crs;
xpt_freeze_devq(cts->ccb_h.path, /*count*/1);
device->inq_flags &= ~SID_CmdQue;
xpt_dev_ccbq_resize(cts->ccb_h.path,
sim->max_dev_openings);
device->flags &= ~CAM_DEV_TAG_AFTER_COUNT;
device->tag_delay_count = 0;
xpt_setup_ccb(&crs.ccb_h, cts->ccb_h.path,
/*priority*/1);
crs.ccb_h.func_code = XPT_REL_SIMQ;
crs.release_flags = RELSIM_RELEASE_AFTER_QEMPTY;
crs.openings
= crs.release_timeout
= crs.qfrozen_cnt
= 0;
xpt_action((union ccb *)&crs);
}
}
}
if (async_update == FALSE)
(*(sim->sim_action))(sim, (union ccb *)cts);
}
#else /* CAM_NEW_TRAN_CODE */
static void
xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
int async_update)
@ -5972,6 +6527,9 @@ xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
}
}
#endif /* CAM_NEW_TRAN_CODE */
static void
xpt_toggle_tags(struct cam_path *path)
{
@ -5991,11 +6549,24 @@ xpt_toggle_tags(struct cam_path *path)
struct ccb_trans_settings cts;
xpt_setup_ccb(&cts.ccb_h, path, 1);
#ifdef CAM_NEW_TRAN_CODE
cts.protocol = PROTO_SCSI;
cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
cts.transport = XPORT_UNSPECIFIED;
cts.transport_version = XPORT_VERSION_UNSPECIFIED;
cts.proto_specific.scsi.flags = 0;
cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
#else /* CAM_NEW_TRAN_CODE */
cts.flags = 0;
cts.valid = CCB_TRANS_TQ_VALID;
#endif /* CAM_NEW_TRAN_CODE */
xpt_set_transfer_settings(&cts, path->device,
/*async_update*/TRUE);
#ifdef CAM_NEW_TRAN_CODE
cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
#else /* CAM_NEW_TRAN_CODE */
cts.flags = CCB_TRANS_TAG_ENB;
#endif /* CAM_NEW_TRAN_CODE */
xpt_set_transfer_settings(&cts, path->device,
/*async_update*/TRUE);
}
@ -6111,7 +6682,9 @@ xptconfigfunc(struct cam_eb *bus, void *arg)
static void
xpt_config(void *arg)
{
/* Now that interrupts are enabled, go find our devices */
/*
* Now that interrupts are enabled, go find our devices
*/
#ifdef CAMDEBUG
/* Setup debugging flags and path */
@ -6252,6 +6825,12 @@ xptaction(struct cam_sim *sim, union ccb *work_ccb)
cpi->unit_number = sim->unit_number;
cpi->bus_id = sim->bus_id;
cpi->base_transfer_speed = 0;
#ifdef CAM_NEW_TRAN_CODE
cpi->protocol = PROTO_UNSPECIFIED;
cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
cpi->transport = XPORT_UNSPECIFIED;
cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
#endif /* CAM_NEW_TRAN_CODE */
cpi->ccb_h.status = CAM_REQ_CMP;
xpt_done(work_ccb);
break;
@ -6330,7 +6909,8 @@ camisr(void *V_queue)
ccb_h->path->bus->sim->devq->send_openings++;
splx(s);
if ((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
if (((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0
&& (ccb_h->status&CAM_STATUS_MASK) != CAM_REQUEUE_REQ)
|| ((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0
&& (dev->ccbq.dev_active == 0))) {

View File

@ -62,6 +62,8 @@ void xpt_free_path(struct cam_path *path);
int xpt_path_comp(struct cam_path *path1,
struct cam_path *path2);
void xpt_print_path(struct cam_path *path);
int xpt_path_string(struct cam_path *path, char *str,
size_t str_len);
path_id_t xpt_path_path_id(struct cam_path *path);
target_id_t xpt_path_target_id(struct cam_path *path);
lun_id_t xpt_path_lun_id(struct cam_path *path);

File diff suppressed because it is too large Load Diff

View File

@ -92,16 +92,8 @@ typedef enum {
SS_TUR = 0x040000, /* Send a Test Unit Ready command to the
* device, then retry the original command.
*/
SS_MANUAL = 0x050000, /*
* This error must be handled manually,
* i.e. the code must look at the asc and
* ascq values and determine the proper
* course of action.
*/
SS_TURSTART = 0x060000, /*
* Send a Test Unit Ready command to the
* device, and if that fails, send a start
* unit.
SS_REQSENSE = 0x050000, /* Send a RequestSense command to the
* device, then retry the original command.
*/
SS_MASK = 0xff0000
} scsi_sense_action;
@ -111,16 +103,10 @@ typedef enum {
SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */
SSQ_MANY = 0x0200, /* send lots of recovery commands */
SSQ_RANGE = 0x0400, /*
* Yes, this is a hack. Basically,
* if this flag is set then it
* represents an ascq range. The
* "correct" way to implement the
* ranges might be to add a special
* field to the sense code table,
* but that would take up a lot of
* additional space. This solution
* isn't as elegant, but is more
* space efficient.
* This table entry represents the
* end of a range of ASCQs that
* have identical error actions
* and text.
*/
SSQ_PRINT_SENSE = 0x0800,
SSQ_MASK = 0xff00
@ -129,14 +115,14 @@ typedef enum {
/* Mask for error status values */
#define SS_ERRMASK 0xff
/* The default error action */
#define SS_DEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
/* The default, retyable, error action */
#define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO
/* Default error action, without an error return value */
#define SS_NEDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
/* The retyable, error action, with table specified error code */
#define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE
/* Default error action, without sense printing or an error return value */
#define SS_NEPDEF SS_RETRY|SSQ_DECREMENT_COUNT
/* Fatal error action, with table specified error code */
#define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE
struct scsi_generic
{
@ -493,7 +479,8 @@ struct scsi_inquiry_data
u_int8_t device;
#define SID_TYPE(inq_data) ((inq_data)->device & 0x1f)
#define SID_QUAL(inq_data) (((inq_data)->device & 0xE0) >> 5)
#define SID_QUAL_LU_CONNECTED 0x00 /* The specified peripheral device
#define SID_QUAL_LU_CONNECTED 0x00 /*
* The specified peripheral device
* type is currently connected to
* logical unit. If the target cannot
* determine whether or not a physical
@ -504,14 +491,16 @@ struct scsi_inquiry_data
* does not mean that the device is
* ready for access by the initiator.
*/
#define SID_QUAL_LU_OFFLINE 0x01 /* The target is capable of supporting
#define SID_QUAL_LU_OFFLINE 0x01 /*
* The target is capable of supporting
* the specified peripheral device type
* on this logical unit; however, the
* physical device is not currently
* connected to this logical unit.
*/
#define SID_QUAL_RSVD 0x02
#define SID_QUAL_BAD_LU 0x03 /* The target is not capable of
#define SID_QUAL_BAD_LU 0x03 /*
* The target is not capable of
* supporting a physical device on
* this logical unit. For this
* peripheral qualifier the peripheral
@ -531,7 +520,7 @@ struct scsi_inquiry_data
#define SCSI_REV_0 0
#define SCSI_REV_CCS 1
#define SCSI_REV_2 2
#define SCSI_REV_3 3
#define SCSI_REV_SPC 3
#define SCSI_REV_SPC2 4
#define SID_ECMA 0x38
@ -569,6 +558,7 @@ struct scsi_inquiry_data
#define SID_SPI_CLOCK_ST 0x00
#define SID_SPI_CLOCK_DT 0x04
#define SID_SPI_CLOCK_DT_ST 0x0C
#define SID_SPI_MASK 0x0F
u_int8_t spi3data;
u_int8_t reserved2;
/*
@ -703,8 +693,10 @@ struct scsi_mode_blk_desc
#define SCSI_STATUS_INTERMED 0x10
#define SCSI_STATUS_INTERMED_COND_MET 0x14
#define SCSI_STATUS_RESERV_CONFLICT 0x18
#define SCSI_STATUS_CMD_TERMINATED 0x22
#define SCSI_STATUS_CMD_TERMINATED 0x22 /* Obsolete in SAM-2 */
#define SCSI_STATUS_QUEUE_FULL 0x28
#define SCSI_STATUS_ACA_ACTIVE 0x30
#define SCSI_STATUS_TASK_ABORTED 0x40
struct scsi_inquiry_pattern {
u_int8_t type;
@ -726,17 +718,23 @@ struct scsi_static_inquiry_pattern {
struct scsi_sense_quirk_entry {
struct scsi_inquiry_pattern inq_pat;
int num_sense_keys;
int num_ascs;
struct sense_key_table_entry *sense_key_info;
struct asc_table_entry *asc_info;
};
struct sense_key_table_entry {
u_int8_t sense_key;
u_int32_t action;
const char *desc;
};
struct asc_table_entry {
u_int8_t asc;
u_int8_t ascq;
u_int32_t action;
#if !defined(SCSI_NO_SENSE_STRINGS)
const char *desc;
#endif
};
struct op_table_entry {
@ -751,6 +749,10 @@ struct scsi_op_quirk_entry {
struct op_table_entry *op_table;
};
typedef enum {
SSS_FLAG_NONE = 0x00,
SSS_FLAG_PRINT_COMMAND = 0x01
} scsi_sense_string_flags;
struct ccb_scsiio;
struct cam_periph;
@ -761,12 +763,22 @@ struct cam_device;
extern const char *scsi_sense_key_text[];
struct sbuf;
__BEGIN_DECLS
const char * scsi_sense_desc(int asc, int ascq,
struct scsi_inquiry_data *inq_data);
scsi_sense_action scsi_error_action(int asc, int ascq,
struct scsi_inquiry_data *inq_data);
void scsi_sense_desc(int sense_key, int asc, int ascq,
struct scsi_inquiry_data *inq_data,
const char **sense_key_desc, const char **asc_desc);
scsi_sense_action scsi_error_action(struct ccb_scsiio* csio,
struct scsi_inquiry_data *inq_data,
u_int32_t sense_flags);
const char * scsi_status_string(struct ccb_scsiio *csio);
#ifdef _KERNEL
int scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb);
int scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb,
scsi_sense_string_flags flags);
char * scsi_sense_string(struct ccb_scsiio *csio,
char *str, int str_len);
void scsi_sense_print(struct ccb_scsiio *csio);
int scsi_interpret_sense(union ccb *ccb,
u_int32_t sense_flags,
@ -774,7 +786,12 @@ int scsi_interpret_sense(union ccb *ccb,
u_int32_t *reduction,
u_int32_t *timeout,
scsi_sense_action error_action);
#else
#else /* _KERNEL */
int scsi_command_string(struct cam_device *device,
struct ccb_scsiio *csio, struct sbuf *sb);
int scsi_sense_sbuf(struct cam_device *device,
struct ccb_scsiio *csio, struct sbuf *sb,
scsi_sense_string_flags flags);
char * scsi_sense_string(struct cam_device *device,
struct ccb_scsiio *csio,
char *str, int str_len);
@ -793,7 +810,6 @@ int scsi_interpret_sense(struct cam_device *device,
#define SF_NO_PRINT 0x02
#define SF_QUIET_IR 0x04 /* Be quiet about Illegal Request reponses */
#define SF_PRINT_ALWAYS 0x08
#define SF_RETRY_SELTO 0x10 /* Retry selection timeouts */
const char * scsi_op_desc(u_int16_t opcode,

View File

@ -1557,10 +1557,8 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
else
sf = 0;
/* Retry selection timeouts */
sf |= SF_RETRY_SELTO;
if ((error = cderror(done_ccb, 0, sf)) == ERESTART) {
error = cderror(done_ccb, CAM_RETRY_SELTO, sf);
if (error == ERESTART) {
/*
* A retry was scheuled, so
* just return.
@ -1659,8 +1657,8 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
* Retry any UNIT ATTENTION type errors. They
* are expected at boot.
*/
error = cderror(done_ccb, 0, SF_RETRY_UA |
SF_NO_PRINT | SF_RETRY_SELTO);
error = cderror(done_ccb, CAM_RETRY_SELTO,
SF_RETRY_UA | SF_NO_PRINT);
if (error == ERESTART) {
/*
* A retry was scheuled, so
@ -1711,15 +1709,21 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
* supported" (0x25) error.
*/
if ((have_sense) && (asc != 0x25)
&& (error_code == SSD_CURRENT_ERROR))
&& (error_code == SSD_CURRENT_ERROR)) {
const char *sense_key_desc;
const char *asc_desc;
scsi_sense_desc(sense_key, asc, ascq,
&cgd.inq_data,
&sense_key_desc,
&asc_desc);
snprintf(announce_buf,
sizeof(announce_buf),
"Attempt to query device "
"size failed: %s, %s",
scsi_sense_key_text[sense_key],
scsi_sense_desc(asc,ascq,
&cgd.inq_data));
else if (SID_TYPE(&cgd.inq_data) == T_CDROM) {
sense_key_desc,
asc_desc);
} else if (SID_TYPE(&cgd.inq_data) == T_CDROM) {
/*
* We only print out an error for
* CDROM type devices. For WORM
@ -2489,8 +2493,8 @@ cdprevent(struct cam_periph *periph, int action)
SSD_FULL_SIZE,
/* timeout */60000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA|SF_NO_PRINT);
xpt_release_ccb(ccb);
@ -2533,8 +2537,8 @@ cdsize(dev_t dev, u_int32_t *size)
SSD_FULL_SIZE,
/* timeout */20000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA|SF_NO_PRINT);
xpt_release_ccb(ccb);
@ -2694,8 +2698,8 @@ cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start,
scsi_cmd->op_code = READ_TOC;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2741,8 +2745,8 @@ cdreadsubchannel(struct cam_periph *periph, u_int32_t mode,
scsi_ulto2b(len, (u_int8_t *)scsi_cmd->data_len);
scsi_cmd->control = 0;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2781,8 +2785,8 @@ cdgetmode(struct cam_periph *periph, struct cd_mode_data *data, u_int32_t page)
scsi_cmd->length = sizeof(*data) & 0xff;
scsi_cmd->opcode = MODE_SENSE;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2828,8 +2832,8 @@ cdsetmode(struct cam_periph *periph, struct cd_mode_data *data)
*/
data->header.medium_type = 0;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2884,8 +2888,8 @@ cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len)
cdb_len,
/*timeout*/50 * 1000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2929,8 +2933,8 @@ cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts,
scsi_cmd->end_s = ends;
scsi_cmd->end_f = endf;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -2973,8 +2977,8 @@ cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex,
scsi_cmd->end_track = etrack;
scsi_cmd->end_index = eindex;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -3012,8 +3016,8 @@ cdpause(struct cam_periph *periph, u_int32_t go)
scsi_cmd->op_code = PAUSE;
scsi_cmd->resume = go;
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA |SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -3040,8 +3044,8 @@ cdstartunit(struct cam_periph *periph)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ 50000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -3068,8 +3072,8 @@ cdstopunit(struct cam_periph *periph, u_int32_t eject)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ 50000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
xpt_release_ccb(ccb);
@ -3139,8 +3143,8 @@ cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ 50000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
if (error != 0)
goto bailout;
@ -3316,8 +3320,8 @@ cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ 50000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
bailout:
@ -3448,8 +3452,8 @@ cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ 50000);
error = cdrunccb(ccb, cderror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO);
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA);
if (error != 0)
goto bailout;

View File

@ -617,8 +617,8 @@ chdone(struct cam_periph *periph, union ccb *done_ccb)
} else {
int error;
error = cherror(done_ccb, 0, SF_RETRY_UA |
SF_NO_PRINT | SF_RETRY_SELTO);
error = cherror(done_ccb, CAM_RETRY_SELTO,
SF_RETRY_UA | SF_NO_PRINT);
/*
* Retry any UNIT ATTENTION type errors. They
* are expected at boot.
@ -868,8 +868,8 @@ chmove(struct cam_periph *periph, struct changer_move *cm)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_MOVE_MEDIUM);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
@ -931,8 +931,8 @@ chexchange(struct cam_periph *periph, struct changer_exchange *ce)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_EXCHANGE_MEDIUM);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
@ -977,8 +977,8 @@ chposition(struct cam_periph *periph, struct changer_position *cp)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_POSITION_TO_ELEMENT);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
@ -1133,8 +1133,8 @@ chgetelemstatus(struct cam_periph *periph,
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
if (error)
@ -1169,8 +1169,8 @@ chgetelemstatus(struct cam_periph *periph,
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
if (error)
@ -1248,8 +1248,8 @@ chielem(struct cam_periph *periph,
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ timeout);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
@ -1335,8 +1335,8 @@ chsetvoltag(struct cam_periph *periph,
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_SEND_VOLTAG);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
@ -1399,9 +1399,8 @@ chgetparams(struct cam_periph *periph)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_MODE_SENSE);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/* sense_flags */ SF_RETRY_UA |
SF_NO_PRINT | SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/* sense_flags */ SF_RETRY_UA|SF_NO_PRINT,
&softc->device_stats);
if (error) {
@ -1412,9 +1411,9 @@ chgetparams(struct cam_periph *periph)
ccb->csio.cdb_io.cdb_bytes;
sms->byte2 &= ~SMS_DBD;
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA |
SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror,
/*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
} else {
/*
@ -1463,9 +1462,9 @@ chgetparams(struct cam_periph *periph)
/* sense_len */ SSD_FULL_SIZE,
/* timeout */ CH_TIMEOUT_MODE_SENSE);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/* sense_flags */ SF_RETRY_UA | SF_NO_PRINT |
SF_RETRY_SELTO, &softc->device_stats);
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO,
/* sense_flags */ SF_RETRY_UA | SF_NO_PRINT,
&softc->device_stats);
if (error) {
if (dbd) {
@ -1475,9 +1474,9 @@ chgetparams(struct cam_periph *periph)
ccb->csio.cdb_io.cdb_bytes;
sms->byte2 &= ~SMS_DBD;
error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0,
/*sense_flags*/ SF_RETRY_UA |
SF_RETRY_SELTO,
error = cam_periph_runccb(ccb, cherror,
/*cam_flags*/ CAM_RETRY_SELTO,
/*sense_flags*/ SF_RETRY_UA,
&softc->device_stats);
} else {
/*

View File

@ -335,6 +335,8 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
struct cam_periph *periph;
struct da_softc *softc;
struct disklabel *label;
struct scsi_read_capacity_data *rcap;
union ccb *ccb;
int unit;
int part;
int error;
@ -342,9 +344,12 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
unit = dkunit(dev);
part = dkpart(dev);
s = splsoftcam();
periph = cam_extend_get(daperiphs, unit);
if (periph == NULL)
if (periph == NULL) {
splx(s);
return (ENXIO);
}
softc = (struct da_softc *)periph->softc;
@ -352,15 +357,13 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
("daopen: dev=%s (unit %d , partition %d)\n", devtoname(dev),
unit, part));
if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
return (error); /* error code from tsleep */
}
if (cam_periph_acquire(periph) != CAM_REQ_CMP)
return(ENXIO);
softc->flags |= DA_FLAG_OPEN;
s = splsoftcam();
if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
/* Invalidate our pack information. */
disk_invalidate(&softc->disk);
@ -369,37 +372,37 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
splx(s);
/* Do a read capacity */
{
struct scsi_read_capacity_data *rcap;
union ccb *ccb;
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
M_TEMP,
M_WAITOK);
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap),
M_TEMP,
M_WAITOK);
ccb = cam_periph_getccb(periph, /*priority*/1);
scsi_read_capacity(&ccb->csio,
/*retries*/1,
/*cbfncp*/dadone,
MSG_SIMPLE_Q_TAG,
rcap,
SSD_FULL_SIZE,
/*timeout*/60000);
ccb->ccb_h.ccb_bp = NULL;
ccb = cam_periph_getccb(periph, /*priority*/1);
scsi_read_capacity(&ccb->csio,
/*retries*/4,
/*cbfncp*/dadone,
MSG_SIMPLE_Q_TAG,
rcap,
SSD_FULL_SIZE,
/*timeout*/60000);
ccb->ccb_h.ccb_bp = NULL;
error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0,
/*sense_flags*/SF_RETRY_UA |
SF_RETRY_SELTO,
&softc->device_stats);
error = cam_periph_runccb(ccb, daerror,
/*cam_flags*/CAM_RETRY_SELTO,
/*sense_flags*/SF_RETRY_UA,
&softc->device_stats);
xpt_release_ccb(ccb);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
xpt_release_ccb(ccb);
if (error == 0) {
dasetgeom(periph, rcap);
}
if (error == 0)
dasetgeom(periph, rcap);
free(rcap, M_TEMP);
}
free(rcap, M_TEMP);
if (error == 0) {
struct ccb_getdev cgd;
@ -430,10 +433,6 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
* softc->params.secs_per_track;
label->d_secperunit = softc->params.sectors;
if (((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)) {
daprevent(periph, PR_PREVENT);
}
/*
* Check to see whether or not the blocksize is set yet.
* If it isn't, set it and then clear the blocksize
@ -445,10 +444,9 @@ daopen(dev_t dev, int flags, int fmt, struct proc *p)
}
}
if (error != 0) {
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) {
daprevent(periph, PR_ALLOW);
}
if (error == 0) {
if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0)
daprevent(periph, PR_PREVENT);
}
cam_periph_unlock(periph);
return (error);
@ -1222,10 +1220,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
else
sf = 0;
/* Retry selection timeouts */
sf |= SF_RETRY_SELTO;
if ((error = daerror(done_ccb, 0, sf)) == ERESTART) {
error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
if (error == ERESTART) {
/*
* A retry was scheuled, so
* just return.
@ -1282,6 +1278,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
/*timeout*/0,
/*getcount_only*/0);
} else {
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
panic("REQ_CMP with QFRZN");
bp->bio_resid = csio->resid;
if (csio->resid > 0)
bp->bio_flags |= BIO_ERROR;
@ -1329,8 +1327,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* Retry any UNIT ATTENTION type errors. They
* are expected at boot.
*/
error = daerror(done_ccb, 0, SF_RETRY_UA |
SF_RETRY_SELTO | SF_NO_PRINT);
error = daerror(done_ccb, CAM_RETRY_SELTO,
SF_RETRY_UA|SF_NO_PRINT);
if (error == ERESTART) {
/*
* A retry was scheuled, so
@ -1346,13 +1344,14 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
struct ccb_getdev cgd;
/* Don't wedge this device's queue */
cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
status = done_ccb->ccb_h.status;
if ((status & CAM_DEV_QFRZN) != 0)
cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
/*reduction*/0,
/*timeout*/0,
/*getcount_only*/0);
xpt_setup_ccb(&cgd.ccb_h,
done_ccb->ccb_h.path,
@ -1380,15 +1379,21 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* unit not supported" (0x25) error.
*/
if ((have_sense) && (asc != 0x25)
&& (error_code == SSD_CURRENT_ERROR))
&& (error_code == SSD_CURRENT_ERROR)) {
const char *sense_key_desc;
const char *asc_desc;
scsi_sense_desc(sense_key, asc, ascq,
&cgd.inq_data,
&sense_key_desc,
&asc_desc);
snprintf(announce_buf,
sizeof(announce_buf),
"Attempt to query device "
"size failed: %s, %s",
scsi_sense_key_text[sense_key],
scsi_sense_desc(asc,ascq,
&cgd.inq_data));
else {
sense_key_desc,
asc_desc);
} else {
if (have_sense)
scsi_sense_print(
&done_ccb->csio);
@ -1412,7 +1417,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
free(rdcap, M_TEMP);
if (announce_buf[0] != '\0')
xpt_announce_periph(periph, announce_buf);
softc->state = DA_STATE_NORMAL;
softc->state = DA_STATE_NORMAL;
/*
* Since our peripheral may be invalidated by an error
* above or an external event, we must release our CCB

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 1998 Justin T. Gibbs.
* Copyright (c) 1997, 1998, 2000 Justin T. Gibbs.
* Copyright (c) 1997, 1998, 1999 Kenneth D. Merry.
* All rights reserved.
*
@ -42,6 +42,7 @@
#include <cam/cam_ccb.h>
#include <cam/cam_extend.h>
#include <cam/cam_periph.h>
#include <cam/cam_queue.h>
#include <cam/cam_xpt_periph.h>
#include <cam/cam_debug.h>
@ -67,13 +68,12 @@ typedef enum {
#define ccb_bp ppriv_ptr1
struct pass_softc {
pass_state state;
pass_flags flags;
u_int8_t pd_type;
struct bio_queue_head bio_queue;
union ccb saved_ccb;
struct devstat device_stats;
dev_t dev;
pass_state state;
pass_flags flags;
u_int8_t pd_type;
union ccb saved_ccb;
struct devstat device_stats;
dev_t dev;
};
#ifndef MIN
@ -85,7 +85,6 @@ struct pass_softc {
static d_open_t passopen;
static d_close_t passclose;
static d_ioctl_t passioctl;
static d_strategy_t passstrategy;
static periph_init_t passinit;
static periph_ctor_t passregister;
@ -112,12 +111,12 @@ PERIPHDRIVER_DECLARE(pass, passdriver);
static struct cdevsw pass_cdevsw = {
/* open */ passopen,
/* close */ passclose,
/* read */ physread,
/* write */ physwrite,
/* read */ noread,
/* write */ nowrite,
/* ioctl */ passioctl,
/* poll */ nopoll,
/* mmap */ nommap,
/* strategy */ passstrategy,
/* strategy */ nostrategy,
/* name */ "pass",
/* maj */ PASS_CDEV_MAJOR,
/* dump */ nodump,
@ -172,9 +171,7 @@ passinit(void)
static void
passoninvalidate(struct cam_periph *periph)
{
int s;
struct pass_softc *softc;
struct bio *q_bp;
struct ccb_setasync csa;
softc = (struct pass_softc *)periph->softc;
@ -193,25 +190,10 @@ passoninvalidate(struct cam_periph *periph)
softc->flags |= PASS_FLAG_INVALID;
/*
* Although the oninvalidate() routines are always called at
* splsoftcam, we need to be at splbio() here to keep the buffer
* queue from being modified while we traverse it.
*/
s = splbio();
/*
* Return all queued I/O with ENXIO.
* XXX Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
while ((q_bp = bioq_first(&softc->bio_queue)) != NULL){
bioq_remove(&softc->bio_queue, q_bp);
q_bp->bio_resid = q_bp->bio_bcount;
q_bp->bio_error = ENXIO;
q_bp->bio_flags |= BIO_ERROR;
biodone(q_bp);
}
splx(s);
if (bootverbose) {
xpt_print_path(periph->path);
@ -267,9 +249,15 @@ passasync(void *callback_arg, u_int32_t code,
passasync, AC_FOUND_DEVICE, cgd);
if (status != CAM_REQ_CMP
&& status != CAM_REQ_INPROG)
&& status != CAM_REQ_INPROG) {
const struct cam_status_entry *entry;
entry = cam_fetch_status_entry(status);
printf("passasync: Unable to attach new device "
"due to status 0x%x\n", status);
"due to status %#x: %s\n", status, entry ?
entry->status_text : "Unknown");
}
break;
}
@ -285,6 +273,7 @@ passregister(struct cam_periph *periph, void *arg)
struct pass_softc *softc;
struct ccb_setasync csa;
struct ccb_getdev *cgd;
int no_tags;
cgd = (struct ccb_getdev *)arg;
if (periph == NULL) {
@ -309,18 +298,19 @@ passregister(struct cam_periph *periph, void *arg)
bzero(softc, sizeof(*softc));
softc->state = PASS_STATE_NORMAL;
softc->pd_type = SID_TYPE(&cgd->inq_data);
bioq_init(&softc->bio_queue);
periph->softc = softc;
cam_extend_set(passperiphs, periph->unit_number, periph);
/*
* We pass in 0 for a blocksize, since we don't
* know what the blocksize of this device is, if
* it even has a blocksize.
*/
devstat_add_entry(&softc->device_stats, "pass", periph->unit_number,
0, DEVSTAT_NO_BLOCKSIZE | DEVSTAT_NO_ORDERED_TAGS,
no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0;
devstat_add_entry(&softc->device_stats, "pass", periph->unit_number, 0,
DEVSTAT_NO_BLOCKSIZE
| (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0),
softc->pd_type |
DEVSTAT_TYPE_IF_SCSI |
DEVSTAT_TYPE_PASS,
@ -447,75 +437,6 @@ passclose(dev_t dev, int flag, int fmt, struct proc *p)
return (0);
}
/*
* Actually translate the requested transfer into one the physical driver
* can understand. The transfer is described by a buf and will include
* only one physical transfer.
*/
static void
passstrategy(struct bio *bp)
{
struct cam_periph *periph;
struct pass_softc *softc;
u_int unit;
int s;
/*
* The read/write interface for the passthrough driver doesn't
* really work right now. So, we just pass back EINVAL to tell the
* user to go away.
*/
bp->bio_error = EINVAL;
goto bad;
/* unit = dkunit(bp->bio_dev); */
/* XXX KDM fix this */
unit = minor(bp->bio_dev) & 0xff;
periph = cam_extend_get(passperiphs, unit);
if (periph == NULL) {
bp->bio_error = ENXIO;
goto bad;
}
softc = (struct pass_softc *)periph->softc;
/*
* Odd number of bytes or negative offset
*/
/* valid request? */
if (bp->bio_blkno < 0) {
bp->bio_error = EINVAL;
goto bad;
}
/*
* Mask interrupts so that the pack cannot be invalidated until
* after we are in the queue. Otherwise, we might not properly
* clean up one of the buffers.
*/
s = splbio();
bioq_insert_tail(&softc->bio_queue, bp);
splx(s);
/*
* Schedule ourselves for performing the work.
*/
xpt_schedule(periph, /* XXX priority */1);
return;
bad:
bp->bio_flags |= BIO_ERROR;
/*
* Correctly set the buf to indicate a completed xfer
*/
bp->bio_resid = bp->bio_bcount;
biodone(bp);
return;
}
static void
passstart(struct cam_periph *periph, union ccb *start_ccb)
{
@ -526,53 +447,17 @@ passstart(struct cam_periph *periph, union ccb *start_ccb)
switch (softc->state) {
case PASS_STATE_NORMAL:
{
struct bio *bp;
s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
splx(s);
xpt_release_ccb(start_ccb);
} else {
bioq_remove(&softc->bio_queue, bp);
devstat_start_transaction(&softc->device_stats);
/*
* XXX JGibbs -
* Interpret the contents of the bp as a CCB
* and pass it to a routine shared by our ioctl
* code and passtart.
* For now, just biodone it with EIO so we don't
* hang.
*/
bp->bio_error = EIO;
bp->bio_flags |= BIO_ERROR;
bp->bio_resid = bp->bio_bcount;
biodone(bp);
bp = bioq_first(&softc->bio_queue);
splx(s);
xpt_action(start_ccb);
}
if (bp != NULL) {
/* Have more work to do, so ensure we stay scheduled */
xpt_schedule(periph, /* XXX priority */1);
}
start_ccb->ccb_h.ccb_type = PASS_CCB_WAITING;
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
splx(s);
wakeup(&periph->ccb_list);
break;
}
}
}
static void
passdone(struct cam_periph *periph, union ccb *done_ccb)
{
@ -582,55 +467,11 @@ passdone(struct cam_periph *periph, union ccb *done_ccb)
softc = (struct pass_softc *)periph->softc;
csio = &done_ccb->csio;
switch (csio->ccb_h.ccb_type) {
case PASS_CCB_BUFFER_IO:
{
struct bio *bp;
cam_status status;
u_int8_t scsi_status;
devstat_trans_flags ds_flags;
status = done_ccb->ccb_h.status;
scsi_status = done_ccb->csio.scsi_status;
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
/* XXX handle errors */
if (!(((status & CAM_STATUS_MASK) == CAM_REQ_CMP)
&& (scsi_status == SCSI_STATUS_OK))) {
int error;
if ((error = passerror(done_ccb, 0, 0)) == ERESTART) {
/*
* A retry was scheuled, so
* just return.
*/
return;
}
/*
* XXX unfreeze the queue after we complete
* the abort process
*/
bp->bio_error = error;
bp->bio_flags |= BIO_ERROR;
}
if ((done_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
ds_flags = DEVSTAT_READ;
else if ((done_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
ds_flags = DEVSTAT_WRITE;
else
ds_flags = DEVSTAT_NO_DATA;
devstat_end_transaction_bio(&softc->device_stats, bp);
biodone(bp);
break;
}
case PASS_CCB_WAITING:
{
/* Caller will release the CCB */
wakeup(&done_ccb->ccb_h.cbfcnp);
return;
}
}
xpt_release_ccb(done_ccb);
}
@ -791,8 +632,8 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
error = cam_periph_runccb(ccb,
(ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
passerror : NULL,
/* cam_flags */ 0,
/* sense_flags */SF_RETRY_UA | SF_RETRY_SELTO,
/* cam_flags */ CAM_RETRY_SELTO,
/* sense_flags */SF_RETRY_UA,
&softc->device_stats);
if (need_unmap != 0)

View File

@ -32,6 +32,10 @@
#include <cam/cam_ccb.h>
/*
* Convert to using a pointer to a ccb in the next major version.
* This should allow us to avoid an extra copy of the CCB data.
*/
#define CAMIOCOMMAND _IOWR(CAM_VERSION, 2, union ccb)
#define CAMGETPASSTHRU _IOWR(CAM_VERSION, 3, union ccb)

View File

@ -594,9 +594,8 @@ ptdone(struct cam_periph *periph, union ccb *done_ccb)
else
sf = 0;
sf |= SF_RETRY_SELTO;
if ((error = pterror(done_ccb, 0, sf)) == ERESTART) {
error = pterror(done_ccb, CAM_RETRY_SELTO, sf);
if (error == ERESTART) {
/*
* A retry was scheuled, so
* just return.

View File

@ -1906,8 +1906,8 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
QFRLS(ccb);
scsi_rewind(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG,
FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT);
error = cam_periph_runccb(ccb, saerror, 0,
SF_NO_PRINT | SF_RETRY_SELTO | SF_RETRY_UA,
error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
SF_NO_PRINT | SF_RETRY_UA,
&softc->device_stats);
QFRLS(ccb);
if (error) {
@ -1924,9 +1924,9 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
scsi_read_block_limits(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
rblim, SSD_FULL_SIZE, 5000);
error = cam_periph_runccb(ccb, saerror, 0,
SF_NO_PRINT | SF_RETRY_UA | SF_RETRY_SELTO,
&softc->device_stats);
error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
SF_NO_PRINT | SF_RETRY_UA, &softc->device_stats);
QFRLS(ccb);
xpt_release_ccb(ccb);
@ -1940,7 +1940,7 @@ samount(struct cam_periph *periph, int oflags, dev_t dev)
softc->max_blk = ~0;
softc->min_blk = 0;
} else {
if (softc->scsi_rev >= SCSI_REV_3) {
if (softc->scsi_rev >= SCSI_REV_SPC) {
softc->blk_gran = RBL_GRAN(rblim);
} else {
softc->blk_gran = 0;

View File

@ -669,7 +669,8 @@ sesioctl(dev_t dev, u_long cmd, caddr_t arg_addr, int flag, struct proc *p)
return (error);
}
#define SES_FLAGS SF_NO_PRINT | SF_RETRY_SELTO | SF_RETRY_UA
#define SES_CFLAGS CAM_RETRY_SELTO
#define SES_FLAGS SF_NO_PRINT | SF_RETRY_UA
static int
ses_runcmd(struct ses_softc *ssc, char *cdb, int cdbl, char *dptr, int *dlenp)
{
@ -698,7 +699,7 @@ ses_runcmd(struct ses_softc *ssc, char *cdb, int cdbl, char *dptr, int *dlenp)
dlen, sizeof (struct scsi_sense_data), cdbl, 60 * 1000);
bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl);
error = cam_periph_runccb(ccb, seserror, 0, SES_FLAGS, NULL);
error = cam_periph_runccb(ccb, seserror, SES_CFLAGS, SES_FLAGS, NULL);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
if (error) {

View File

@ -762,6 +762,7 @@ kern/vfs_vnops.c standard
#
libkern/arc4random.c standard
libkern/bcd.c standard
libkern/bsearch.c standard
libkern/index.c standard
libkern/inet_ntoa.c standard
libkern/mcount.c optional profiling-routine

View File

@ -37,6 +37,9 @@
#ifndef _AIC7XXX_FREEBSD_H_
#define _AIC7XXX_FREEBSD_H_
#ifdef CAM_NEW_TRAN_CODE
#define AHC_NEW_TRAN_SETTINGS
#endif /* CAM_NEW_TRAN_CODE */
#include <opt_aic7xxx.h> /* for config options */
#include <pci.h> /* for NPCI */

View File

@ -37,6 +37,9 @@
#ifndef _AIC7XXX_FREEBSD_H_
#define _AIC7XXX_FREEBSD_H_
#ifdef CAM_NEW_TRAN_CODE
#define AHC_NEW_TRAN_SETTINGS
#endif /* CAM_NEW_TRAN_CODE */
#include <opt_aic7xxx.h> /* for config options */
#include <pci.h> /* for NPCI */

View File

@ -29,14 +29,27 @@
*/
#include <sys/param.h>
#include <sys/sbuf.h>
#ifdef _KERNEL
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/sbuf.h>
#include <sys/systm.h>
#include <machine/stdarg.h>
#else /* _KERNEL */
#include <stdarg.h>
#endif /* _KERNEL */
#ifdef _KERNEL
MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
#define SBMALLOC(size) malloc(size, M_SBUF, M_WAITOK)
#define SBFREE(buf) free(buf, M_SBUF)
#else /* _KERNEL */
#define KASSERT(e, m)
#define SBMALLOC(size) malloc(size)
#define SBFREE(buf) free(buf)
#define min(x,y) MIN(x,y)
#endif /* _KERNEL */
/*
* Predicates
@ -55,7 +68,7 @@ MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers");
/*
* Debugging support
*/
#ifdef INVARIANTS
#if defined(_KERNEL) && defined(INVARIANTS)
static void
_assert_sbuf_integrity(char *fun, struct sbuf *s)
{
@ -76,10 +89,10 @@ _assert_sbuf_state(char *fun, struct sbuf *s, int state)
}
#define assert_sbuf_integrity(s) _assert_sbuf_integrity(__FUNCTION__, (s))
#define assert_sbuf_state(s, i) _assert_sbuf_state(__FUNCTION__, (s), (i))
#else
#else /* _KERNEL && INVARIANTS */
#define assert_sbuf_integrity(s) do { } while (0)
#define assert_sbuf_state(s, i) do { } while (0)
#endif
#endif /* _KERNEL && INVARIANTS */
/*
* Initialize an sbuf.
@ -102,7 +115,7 @@ sbuf_new(struct sbuf *s, char *buf, int length, int flags)
s->s_buf = buf;
return (0);
}
s->s_buf = malloc(s->s_size, M_SBUF, M_WAITOK);
s->s_buf = (char *)SBMALLOC(s->s_size);
if (s->s_buf == NULL)
return (-1);
SBUF_SETFLAG(s, SBUF_DYNAMIC);
@ -147,7 +160,7 @@ sbuf_setpos(struct sbuf *s, int pos)
* Append a string to an sbuf.
*/
int
sbuf_cat(struct sbuf *s, char *str)
sbuf_cat(struct sbuf *s, const char *str)
{
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
@ -168,7 +181,7 @@ sbuf_cat(struct sbuf *s, char *str)
* Copy a string into an sbuf.
*/
int
sbuf_cpy(struct sbuf *s, char *str)
sbuf_cpy(struct sbuf *s, const char *str)
{
assert_sbuf_integrity(s);
assert_sbuf_state(s, 0);
@ -177,15 +190,6 @@ sbuf_cpy(struct sbuf *s, char *str)
return (sbuf_cat(s, str));
}
/*
* PCHAR function for sbuf_printf()
*/
static void
_sbuf_pchar(int c, void *v)
{
sbuf_putc((struct sbuf *)v, c);
}
/*
* Format the given arguments and append the resulting string to an sbuf.
*/
@ -205,9 +209,22 @@ sbuf_printf(struct sbuf *s, char *fmt, ...)
return (-1);
va_start(ap, fmt);
len = kvprintf(fmt, _sbuf_pchar, s, 10, ap);
len = vsnprintf(&s->s_buf[s->s_len], s->s_size - s->s_len, fmt, ap);
va_end(ap);
/*
* s->s_len is the length of the string, without the terminating nul.
* When updating s->s_len, we must subtract 1 from the length that
* we passed into vsnprintf() because that length includes the
* terminating nul.
*
* vsnprintf() returns the amount that would have been copied,
* given sufficient space, hence the min() calculation below.
*/
s->s_len += min(len, s->s_size - s->s_len - 1);
if (!SBUF_HASROOM(s))
SBUF_SETFLAG(s, SBUF_OVERFLOWED);
KASSERT(s->s_len < s->s_size,
("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size));
@ -296,6 +313,6 @@ sbuf_delete(struct sbuf *s)
/* don't care if it's finished or not */
if (SBUF_ISDYNAMIC(s))
free(s->s_buf, M_SBUF);
SBFREE(s->s_buf);
bzero(s, sizeof *s);
}

83
sys/libkern/bsearch.c Normal file
View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
#endif /* LIBC_SCCS and not lint */
#include <stddef.h>
#include <stdlib.h>
/*
* Perform a binary search.
*
* The code below is a bit sneaky. After a comparison fails, we
* divide the work in half by moving either left or right. If lim
* is odd, moving left simply involves halving lim: e.g., when lim
* is 5 we look at item 2, so we change lim to 2 so that we will
* look at items 0 & 1. If lim is even, the same applies. If lim
* is odd, moving right again involes halving lim, this time moving
* the base up one item past p: e.g., when lim is 5 we change base
* to item 3 and make lim 2 so that we will look at items 3 and 4.
* If lim is even, however, we have to shrink it by one before
* halving: e.g., when lim is 4, we still looked at item 2, so we
* have to make lim 3, then halve, obtaining 1, so that we will only
* look at item 3.
*/
void *
bsearch(key, base0, nmemb, size, compar)
register const void *key;
const void *base0;
size_t nmemb;
register size_t size;
register int (*compar) __P((const void *, const void *));
{
register const char *base = base0;
register size_t lim;
register int cmp;
register const void *p;
for (lim = nmemb; lim != 0; lim >>= 1) {
p = base + (lim >> 1) * size;
cmp = (*compar)(key, p);
if (cmp == 0)
return ((void *)p);
if (cmp > 0) { /* key > p: move right */
base = (const char *)p + size;
lim--;
} /* else move left */
}
return (NULL);
}

View File

@ -66,6 +66,8 @@ static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); }
/* Prototypes for non-quad routines. */
u_int32_t arc4random __P((void));
int bcmp __P((const void *, const void *, size_t));
void *bsearch __P((const void *, const void *, size_t,
size_t, int (*)(const void *, const void *)));
#ifndef HAVE_INLINE_FFS
int ffs __P((int));
#endif

View File

@ -46,14 +46,15 @@ struct sbuf {
int s_flags; /* flags */
};
__BEGIN_DECLS
/*
* API functions
*/
int sbuf_new(struct sbuf *s, char *buf, int length, int flags);
void sbuf_clear(struct sbuf *s);
int sbuf_setpos(struct sbuf *s, int pos);
int sbuf_cat(struct sbuf *s, char *str);
int sbuf_cpy(struct sbuf *s, char *str);
int sbuf_cat(struct sbuf *s, const char *str);
int sbuf_cpy(struct sbuf *s, const char *str);
int sbuf_printf(struct sbuf *s, char *fmt, ...);
int sbuf_putc(struct sbuf *s, int c);
int sbuf_overflowed(struct sbuf *s);
@ -61,5 +62,6 @@ void sbuf_finish(struct sbuf *s);
char *sbuf_data(struct sbuf *s);
int sbuf_len(struct sbuf *s);
void sbuf_delete(struct sbuf *s);
__END_DECLS
#endif

View File

@ -57,8 +57,8 @@ BEGIN {
print "#include <netinet6/in6_var.h>"
print "#include <netinet6/nd6.h>"
print "#include <netinet6/ip6_mroute.h>"
print "#include <cam/cam.h>"
print "#include <stdio.h>"
print "#include <cam/cam.h>"
print ""
print ioctl_includes
print ""