*** src/Makefile.inc1.orig --- src/Makefile.inc1 *************** *** 695,700 **** --- 695,701 ---- 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,718 **** --- 714,720 ---- # # lib*: csu libgcc_pic # libatm: libmd + # libcam: libsbuf # libcrypt: libmd # libdialog: libncurses # libedit: libncurses *************** *** 774,781 **** .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} .if exists(${.CURDIR}/${_lib}) cd ${.CURDIR}/${_lib}; \ ${MAKE} depend; \ --- 776,783 ---- .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/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; \ *** src/lib/Makefile.orig --- src/lib/Makefile *************** *** 16,26 **** # libskey must be built before libpam. # libtacplus must be built before libpam. # libutil must be built before libpam. # # Otherwise, the SUBDIR list should be in alphabetical order. SUBDIR= ${_csu} libcom_err libcrypt msun libmd \ ! libncurses libradius libskey libtacplus libutil \ ${_compat} libalias libatm ${_libbind} libc ${_libc_r} libcalendar \ libcam libcompat libdevstat libdisk libedit libfetch libform \ libftpio libgnumalloc ${_libio} libipsec libipx libisc libkvm libmenu \ --- 16,27 ---- # 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 libsbuf \ ${_compat} libalias libatm ${_libbind} libc ${_libc_r} libcalendar \ libcam libcompat libdevstat libdisk libedit libfetch libform \ libftpio libgnumalloc ${_libio} libipsec libipx libisc libkvm libmenu \ *** src/lib/libcam/Makefile.orig --- src/lib/libcam/Makefile *************** *** 2,40 **** 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 ! 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 ! .PATH: ${.CURDIR}/../../sys/cam/scsi ${.CURDIR}/../../sys/cam ! SDIR= ${.CURDIR}/../../sys ! CFLAGS+=-I${.CURDIR} -I${SDIR} .include --- 2,43 ---- 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 ! ! 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 ! .PATH: ${.CURDIR}/../../sys/cam/scsi ${.CURDIR}/../../sys/cam ! SDIR= ${.CURDIR}/../../sys ! CFLAGS+= -I${.CURDIR} -I${SDIR} .include *** /dev/null Fri Mar 23 13:41:22 2001 --- src/lib/libsbuf/Makefile Fri Mar 23 15:08:01 2001 *************** *** 0 **** --- 1,11 ---- + # $FreeBSD$ + + LIB= sbuf + SRCS= subr_sbuf.c + + .PATH: ${.CURDIR}/../../sys/kern + + SDIR= ${.CURDIR}/../../sys + CFLAGS+=-I${SDIR} + + .include *** src/sbin/camcontrol/Makefile.orig --- src/sbin/camcontrol/Makefile *************** *** 6,12 **** SDIR= ${.CURDIR}/../../sys CFLAGS+= -I${SDIR} ! DPADD= ${LIBCAM} ! LDADD+= -lcam .include --- 6,12 ---- SDIR= ${.CURDIR}/../../sys CFLAGS+= -I${SDIR} ! DPADD= ${LIBCAM} ${LIBSBUF} ! LDADD+= -lcam -lsbuf .include *** src/sbin/camcontrol/camcontrol.c.orig --- src/sbin/camcontrol/camcontrol.c *************** *** 451,462 **** 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_freeccb(ccb); --- 451,458 ---- perror("error sending test unit ready"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); *************** *** 472,483 **** 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); } } --- 468,475 ---- error = 1; if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } } *************** *** 522,533 **** 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_freeccb(ccb); --- 514,521 ---- perror("error sending start unit"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); *************** *** 558,569 **** "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); } } --- 546,553 ---- "Error received from stop unit command\n"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } } *************** *** 702,713 **** 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_freeccb(ccb); --- 686,693 ---- perror("error sending SCSI inquiry"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); *************** *** 718,729 **** 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); } } --- 698,705 ---- error = 1; if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } } *************** *** 792,803 **** 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_freeccb(ccb); --- 768,775 ---- warn("error getting serial number"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); *************** *** 809,820 **** 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); } } --- 781,788 ---- error = 1; if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } } *************** *** 871,883 **** 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); retval = 1; --- 839,847 ---- else warnx(error_string); if (arglist & CAM_ARG_VERBOSE) ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); retval = 1; *************** *** 1265,1292 **** 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); } 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) { struct scsi_sense_data *sense; int error_code, sense_key, asc, ascq; --- 1229,1251 ---- perror("error reading defect list"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } error = 1; goto defect_bailout; } 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_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,1334 **** --- 1286,1303 ---- } 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,1495 **** 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_freeccb(ccb); cam_close_device(device); --- 1453,1460 ---- if (((retval = cam_send_ccb(device, ccb)) < 0) || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); cam_close_device(device); *************** *** 1537,1548 **** 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_freeccb(ccb); cam_close_device(device); --- 1502,1509 ---- if (((retval = cam_send_ccb(device, ccb)) < 0) || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) { if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } cam_freeccb(ccb); cam_close_device(device); *************** *** 1826,1837 **** 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); } error = 1; --- 1787,1794 ---- warnx("error sending command"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } error = 1; *************** *** 2053,2060 **** } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { ! warnx("XPT_REL_SIMQ CCB failed, status %#x", ! ccb->ccb_h.status); retval = 1; goto tagcontrol_bailout; } --- 2010,2018 ---- } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { ! warnx("XPT_REL_SIMQ CCB failed"); ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); retval = 1; goto tagcontrol_bailout; } *************** *** 2077,2084 **** } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { ! warnx("XPT_GDEV_STATS CCB failed, status %#x", ! ccb->ccb_h.status); retval = 1; goto tagcontrol_bailout; } --- 2035,2043 ---- } if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { ! warnx("XPT_GDEV_STATS CCB failed"); ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); retval = 1; goto tagcontrol_bailout; } *************** *** 2178,2185 **** warn("get_cpi: error sending Path Inquiry CCB"); if (arglist & CAM_ARG_VERBOSE) ! fprintf(stderr, "CAM status is %#x\n", ! ccb->ccb_h.status); retval = 1; --- 2137,2144 ---- warn("get_cpi: error sending Path Inquiry CCB"); if (arglist & CAM_ARG_VERBOSE) ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); retval = 1; *************** *** 2189,2196 **** 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); retval = 1; --- 2148,2155 ---- if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { if (arglist & CAM_ARG_VERBOSE) ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); retval = 1; *************** *** 2367,2379 **** if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_GET_TRAN_SETTINGS CCB"); 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); retval = 1; goto get_print_cts_bailout; } --- 2326,2343 ---- 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"); ! 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,2509 **** if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_PATH_INQ CCB"); 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); retval = 1; goto ratecontrol_bailout; } --- 2461,2480 ---- 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"); ! if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); ! } retval = 1; goto ratecontrol_bailout; } *************** *** 2645,2657 **** if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_SET_TRAN_SETTINGS CCB"); 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); retval = 1; goto ratecontrol_bailout; } --- 2616,2635 ---- 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"); ! if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); ! } retval = 1; goto ratecontrol_bailout; } *************** *** 2850,2861 **** 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); } error = 1; goto scsiformat_bailout; --- 2828,2835 ---- warnx(errstr); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } error = 1; goto scsiformat_bailout; *************** *** 2904,2916 **** 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); } error = 1; goto scsiformat_bailout; --- 2878,2885 ---- if (retval < 0) { warn("error sending CAMIOCOMMAND ioctl"); if (arglist & CAM_ARG_VERBOSE) { ! cam_error_print(device, ccb, CAM_ESF_ALL, ! CAM_EPF_ALL, stderr); } error = 1; goto scsiformat_bailout; *************** *** 2919,2925 **** status = ccb->ccb_h.status & CAM_STATUS_MASK; if ((status != CAM_REQ_CMP) ! && (status == CAM_SCSI_STATUS_ERROR)) { struct scsi_sense_data *sense; int error_code, sense_key, asc, ascq; --- 2888,2895 ---- status = ccb->ccb_h.status & CAM_STATUS_MASK; if ((status != CAM_REQ_CMP) ! && (status == CAM_SCSI_STATUS_ERROR) ! && ((status & CAM_AUTOSNS_VALID) != 0)) { struct scsi_sense_data *sense; int error_code, sense_key, asc, ascq; *************** *** 2970,2982 **** sleep(1); } else { warnx("Unexpected SCSI error during format"); ! scsi_sense_print(device, &ccb->csio, stderr); error = 1; goto scsiformat_bailout; } } else if (status != CAM_REQ_CMP) { warnx("Unexpected CAM status %#x", status); error = 1; goto scsiformat_bailout; } --- 2940,2956 ---- sleep(1); } else { warnx("Unexpected SCSI error during format"); ! 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; } *** src/share/man/man9/sbuf.9.orig --- src/share/man/man9/sbuf.9 *************** *** 52,60 **** .Ft int .Fn sbuf_setpos "struct sbuf *s" "int pos" .Ft int ! .Fn sbuf_cat "struct sbuf *s" "char *str" .Ft int ! .Fn sbuf_cpy "struct sbuf *s" "char *str" .Ft int .Fn sbuf_printf "struct sbuf *s" "char *fmt" "..." .Ft int --- 52,60 ---- .Ft int .Fn sbuf_setpos "struct sbuf *s" "int pos" .Ft int ! .Fn sbuf_cat "struct sbuf *s" "const char *str" .Ft int ! .Fn sbuf_cpy "struct sbuf *s" "const char *str" .Ft int .Fn sbuf_printf "struct sbuf *s" "char *fmt" "..." .Ft int *************** *** 177,183 **** modified using .Fn sbuf_setpos , .Fn sbuf_cat , ! .Fn sbuf_cpu , .Fn sbuf_printf or .Fn sbuf_putc . --- 177,183 ---- modified using .Fn sbuf_setpos , .Fn sbuf_cat , ! .Fn sbuf_cpy , .Fn sbuf_printf or .Fn sbuf_putc . *** src/share/mk/bsd.libnames.mk.orig --- src/share/mk/bsd.libnames.mk *************** *** 80,85 **** --- 80,86 ---- 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 *** src/sys/cam/cam.c.orig --- src/sys/cam/cam.c *************** *** 29,36 **** --- 29,100 ---- */ #include + #ifdef _KERNEL + #include + #else /* _KERNEL */ + #include + #include + #endif /* _KERNEL */ + #include + #include + #include + #include + + #ifdef _KERNEL + #include + #include + #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,109 **** --- 171,339 ---- } 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); + + #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: + sbuf_printf(&sb, "Command format not supported\n"); + 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) + && (proto_flags != CAM_EPF_NONE)) { + + switch (ccb->ccb_h.func_code) { + case XPT_SCSI_IO: + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != + CAM_SCSI_STATUS_ERROR) + break; + + 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_EPF_NORMAL) + || (proto_flags & CAM_EPF_ALL)) + && (ccb->csio.scsi_status == SCSI_STATUS_CHECK_COND) + && ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)) { + + #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: + sbuf_cat(&sb, path_str); + sbuf_printf(&sb, "No protocol specific information\n"); + + 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 */ *** src/sys/cam/cam.h.orig --- src/sys/cam/cam.h *************** *** 85,94 **** */ #define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0) ! /* CAM flags */ typedef enum { CAM_FLAG_NONE = 0x00, ! CAM_EXPECT_INQ_CHANGE = 0x01 } cam_flags; /* CAM Status field values */ --- 85,95 ---- */ #define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0) ! /* CAM flags XXX Move to cam_periph.h ??? */ typedef enum { CAM_FLAG_NONE = 0x00, ! CAM_EXPECT_INQ_CHANGE = 0x01, ! CAM_RETRY_SELTO = 0x02 /* Retry Selection Timeouts */ } cam_flags; /* CAM Status field values */ *************** *** 139,145 **** 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_SCSI_BUSY, /* SCSI Bus Busy */ CAM_DEV_QFRZN = 0x40, /* The DEV queue is frozen w/this err */ --- 140,146 ---- 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 enabled for target mode */ CAM_SCSI_BUSY, /* SCSI Bus Busy */ CAM_DEV_QFRZN = 0x40, /* The DEV queue is frozen w/this err */ *************** *** 155,160 **** --- 156,186 ---- 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 = 0x04 + } cam_error_proto_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,169 **** --- 190,213 ---- 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 *** src/sys/cam/cam_ccb.h.orig --- src/sys/cam/cam_ccb.h *************** *** 34,39 **** --- 34,42 ---- #include #include #include + #ifdef CAM_NEW_TRAN_CODE + #include + #endif /* CAM_NEW_TRAN_CODE */ #ifndef _KERNEL #include #endif *************** *** 172,178 **** /* 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, /* HBA execute engine request */ /* Target mode commands: 0x30->0x3F */ --- 175,181 ---- /* 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, /* HBA execute engine request */ /* Target mode commands: 0x30->0x3F */ *************** *** 205,210 **** --- 208,240 ---- (((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,263 **** 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 serial_num_len; }; --- 287,293 ---- struct ccb_hdr ccb_h; struct scsi_inquiry_data inq_data; u_int8_t serial_num[252]; ! u_int8_t reserved; u_int8_t serial_num_len; }; *************** *** 486,492 **** --- 516,528 ---- 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,512 **** --- 543,557 ---- 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,668 **** union ccb *termio_ccb; /* Pointer to CCB to terminate */ }; /* 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 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 u_int sync_period; u_int sync_offset; u_int bus_width; }; /* * Calculate the geometry parameters for a device * give the block size and volume size in blocks. --- 689,765 ---- 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 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 + 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. *** src/sys/cam/cam_debug.h.orig --- src/sys/cam/cam_debug.h *************** *** 53,59 **** extern struct cam_path *cam_dpath; /* Current debug levels set */ extern u_int32_t cam_dflags; ! /* Printf delay value (to prevent scrolling */ extern u_int32_t cam_debug_delay; /* Debugging macros. */ --- 53,59 ---- extern struct cam_path *cam_dpath; /* Current debug levels set */ extern u_int32_t cam_dflags; ! /* Printf delay value (to prevent scrolling) */ extern u_int32_t cam_debug_delay; /* Debugging macros. */ *** src/sys/cam/cam_periph.c.orig --- src/sys/cam/cam_periph.c *************** *** 62,67 **** --- 62,81 ---- static void camperiphdone(struct cam_periph *periph, union ccb *done_ccb); static void camperiphfree(struct cam_periph *periph); + static int camperiphscsistatuserror(union ccb *ccb, + cam_flags camflags, + u_int32_t sense_flags, + union ccb *save_ccb, + int *openings, + u_int32_t *relsim_flags, + u_int32_t *timeout); + static int camperiphscsisenseerror(union ccb *ccb, + cam_flags camflags, + u_int32_t sense_flags, + union ccb *save_ccb, + int *openings, + u_int32_t *relsim_flags, + u_int32_t *timeout); static int nperiph_drivers; struct periph_driver **periph_drivers; *************** *** 473,487 **** { int error; while ((periph->flags & CAM_PERIPH_LOCKED) != 0) { periph->flags |= CAM_PERIPH_LOCK_WANTED; ! if ((error = tsleep(periph, priority, "caplck", 0)) != 0) return error; } - if (cam_periph_acquire(periph) != CAM_REQ_CMP) - return(ENXIO); - periph->flags |= CAM_PERIPH_LOCKED; return 0; } --- 487,509 ---- { int error; + /* + * Increment the reference count on the peripheral + * while we wait for our lock attempt to succeed + * to ensure the peripheral doesn't dissappear + * out from under us while we sleep. + */ + if (cam_periph_acquire(periph) != CAM_REQ_CMP) + return(ENXIO); + while ((periph->flags & CAM_PERIPH_LOCKED) != 0) { periph->flags |= CAM_PERIPH_LOCK_WANTED; ! if ((error = tsleep(periph, priority, "caplck", 0)) != 0) { ! cam_periph_release(periph); return error; + } } periph->flags |= CAM_PERIPH_LOCKED; return 0; } *************** *** 891,903 **** --- 913,928 ---- static void camperiphdone(struct cam_periph *periph, union ccb *done_ccb) { + union ccb *saved_ccb; cam_status status; int frozen; int sense; struct scsi_start_stop_unit *scsi_cmd; u_int32_t relsim_flags, timeout; u_int32_t qfrozen_cnt; + int xpt_done_ccb; + xpt_done_ccb = FALSE; status = done_ccb->ccb_h.status; frozen = (status & CAM_DEV_QFRZN) != 0; sense = (status & CAM_AUTOSNS_VALID) != 0; *************** *** 905,910 **** --- 930,936 ---- timeout = 0; relsim_flags = 0; + saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr; /* * Unfreeze the queue once if it is already frozen.. *************** *** 918,932 **** } switch (status) { - case CAM_REQ_CMP: ! /* * If we have successfully taken a device from the not ! * ready to ready state, re-scan the device and re-get the ! * inquiry information. Many devices (mostly disks) don't ! * properly report their inquiry information unless they ! * are spun up. */ if (done_ccb->ccb_h.func_code == XPT_SCSI_IO) { scsi_cmd = (struct scsi_start_stop_unit *) --- 944,962 ---- } switch (status) { case CAM_REQ_CMP: ! { /* * If we have successfully taken a device from the not ! * ready to ready state, re-scan the device and re-get ! * the inquiry information. Many devices (mostly disks) ! * don't properly report their inquiry information unless ! * they are spun up. ! * ! * If we manually retrieved sense into a CCB and got ! * something other than "NO SENSE" send the updated CCB ! * back to the client via xpt_done() to be processed via ! * the error recovery code again. */ if (done_ccb->ccb_h.func_code == XPT_SCSI_IO) { scsi_cmd = (struct scsi_start_stop_unit *) *************** *** 935,949 **** if (scsi_cmd->opcode == START_STOP_UNIT) xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL); } bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb, sizeof(union ccb)); periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG; ! xpt_action(done_ccb); break; case CAM_SCSI_STATUS_ERROR: scsi_cmd = (struct scsi_start_stop_unit *) &done_ccb->csio.cdb_io.cdb_bytes; --- 965,999 ---- if (scsi_cmd->opcode == START_STOP_UNIT) xpt_async(AC_INQ_CHANGED, done_ccb->ccb_h.path, NULL); + if (scsi_cmd->opcode == REQUEST_SENSE) { + u_int sense_key; + + sense_key = saved_ccb->csio.sense_data.flags; + sense_key &= SSD_KEY; + if (sense_key != SSD_KEY_NO_SENSE) { + saved_ccb->ccb_h.flags |= + CAM_AUTOSNS_VALID; + xpt_print_path(saved_ccb->ccb_h.path); + printf("Recovered Sense\n"); + #if 0 + scsi_sense_print(&saved_ccb->csio); + #endif + cam_error_print(saved_ccb, CAM_ESF_ALL, + CAM_EPF_ALL); + xpt_done_ccb = TRUE; + } + } } bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb, sizeof(union ccb)); periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG; ! if (xpt_done_ccb == FALSE) ! xpt_action(done_ccb); break; + } case CAM_SCSI_STATUS_ERROR: scsi_cmd = (struct scsi_start_stop_unit *) &done_ccb->csio.cdb_io.cdb_bytes; *************** *** 982,988 **** xpt_action(done_ccb); ! } else if (done_ccb->ccb_h.retry_count > 0) { /* * In this case, the error recovery * command failed, but we've got --- 1032,1038 ---- xpt_action(done_ccb); ! } else if (done_ccb->ccb_h.retry_count > 1) { /* * In this case, the error recovery * command failed, but we've got *************** *** 1001,1008 **** } else { /* ! * Copy the original CCB back and ! * send it back to the caller. */ bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb, sizeof(union ccb)); --- 1051,1059 ---- } else { /* ! * Perform the final retry with the original ! * CCB so that final error processing is ! * performed by the owner of the CCB. */ bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb, sizeof(union ccb)); *************** *** 1039,1044 **** --- 1090,1102 ---- } /* decrement the retry count */ + /* + * XXX This isn't appropriate in all cases. Restructure, + * so that the retry count is only decremented on an + * actual retry. Remeber that the orignal ccb had its + * retry count dropped before entering recovery, so + * doing it again is a bug. + */ if (done_ccb->ccb_h.retry_count > 0) done_ccb->ccb_h.retry_count--; *************** *** 1047,1052 **** --- 1105,1112 ---- /*openings*/0, /*timeout*/timeout, /*getcount_only*/0); + if (xpt_done_ccb == TRUE) + (*done_ccb->ccb_h.cbfcnp)(periph, done_ccb); } /* *************** *** 1113,1581 **** } ! /* ! * Generic error handler. Peripheral drivers usually filter ! * out the errors that they handle in a unique mannor, then ! * call this function. ! */ ! int ! cam_periph_error(union ccb *ccb, cam_flags camflags, ! u_int32_t sense_flags, union ccb *save_ccb) { ! cam_status status; ! int frozen; ! int sense; ! int error; ! int openings; ! int retry; ! u_int32_t relsim_flags; ! u_int32_t timeout; ! ! status = ccb->ccb_h.status; ! frozen = (status & CAM_DEV_QFRZN) != 0; ! sense = (status & CAM_AUTOSNS_VALID) != 0; ! status &= CAM_STATUS_MASK; ! relsim_flags = 0; ! switch (status) { ! case CAM_REQ_CMP: ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) ! ccb->ccb_h.retry_count--; error = 0; break; ! case CAM_AUTOSENSE_FAIL: ! case CAM_SCSI_STATUS_ERROR: ! switch (ccb->csio.scsi_status) { ! case SCSI_STATUS_OK: ! case SCSI_STATUS_COND_MET: ! case SCSI_STATUS_INTERMED: ! case SCSI_STATUS_INTERMED_COND_MET: ! error = 0; ! break; ! case SCSI_STATUS_CMD_TERMINATED: ! case SCSI_STATUS_CHECK_COND: ! if (sense != 0) { ! struct scsi_sense_data *sense; ! int error_code, sense_key, asc, ascq; ! struct cam_periph *periph; ! scsi_sense_action err_action; ! struct ccb_getdev cgd; ! sense = &ccb->csio.sense_data; ! scsi_extract_sense(sense, &error_code, ! &sense_key, &asc, &ascq); ! periph = xpt_path_periph(ccb->ccb_h.path); /* ! * Grab the inquiry data for this device. */ ! xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, ! /*priority*/ 1); ! cgd.ccb_h.func_code = XPT_GDEV_TYPE; ! xpt_action((union ccb *)&cgd); ! err_action = scsi_error_action(asc, ascq, ! &cgd.inq_data); ! /* ! * Send a Test Unit Ready to the device. ! * If the 'many' flag is set, we send 120 ! * test unit ready commands, one every half ! * second. Otherwise, we just send one TUR. ! * We only want to do this if the retry ! * count has not been exhausted. ! */ ! if (((err_action & SS_MASK) == SS_TUR) ! && save_ccb != NULL ! && ccb->ccb_h.retry_count > 0) { ! /* ! * Since error recovery is already ! * in progress, don't attempt to ! * process this error. It is probably ! * related to the error that caused ! * the currently active error recovery ! * action. Also, we only have ! * space for one saved CCB, so if we ! * had two concurrent error recovery ! * actions, we would end up ! * over-writing one error recovery ! * CCB with another one. ! */ ! if (periph->flags & ! CAM_PERIPH_RECOVERY_INPROG) { ! error = ERESTART; ! break; ! } ! periph->flags |= ! CAM_PERIPH_RECOVERY_INPROG; ! /* decrement the number of retries */ ! if ((err_action & ! SSQ_DECREMENT_COUNT) != 0) { ! retry = 1; ! ccb->ccb_h.retry_count--; ! } ! bcopy(ccb, save_ccb, sizeof(*save_ccb)); ! /* ! * We retry this one every half ! * second for a minute. If the ! * device hasn't become ready in a ! * minute's time, it's unlikely to ! * ever become ready. If the table ! * doesn't specify SSQ_MANY, we can ! * only try this once. Oh well. ! */ ! if ((err_action & SSQ_MANY) != 0) ! scsi_test_unit_ready(&ccb->csio, ! /*retries*/120, ! camperiphdone, ! MSG_SIMPLE_Q_TAG, ! SSD_FULL_SIZE, ! /*timeout*/5000); ! else ! scsi_test_unit_ready(&ccb->csio, ! /*retries*/1, ! camperiphdone, ! MSG_SIMPLE_Q_TAG, ! SSD_FULL_SIZE, ! /*timeout*/5000); ! /* release the queue after .5 sec. */ ! relsim_flags = ! RELSIM_RELEASE_AFTER_TIMEOUT; ! timeout = 500; ! /* ! * Drop the priority to 0 so that ! * we are the first to execute. Also ! * freeze the queue after this command ! * is sent so that we can restore the ! * old csio and have it queued in the ! * proper order before we let normal ! * transactions go to the drive. ! */ ! ccb->ccb_h.pinfo.priority = 0; ! ccb->ccb_h.flags |= CAM_DEV_QFREEZE; ! /* ! * Save a pointer to the original ! * CCB in the new CCB. ! */ ! ccb->ccb_h.saved_ccb_ptr = save_ccb; ! error = ERESTART; ! } ! /* ! * Send a start unit command to the device, ! * and then retry the command. We only ! * want to do this if the retry count has ! * not been exhausted. If the user ! * specified 0 retries, then we follow ! * their request and do not retry. ! */ ! else if (((err_action & SS_MASK) == SS_START) ! && save_ccb != NULL ! && ccb->ccb_h.retry_count > 0) { ! int le; ! /* ! * Only one error recovery action ! * at a time. See above. ! */ ! if (periph->flags & ! CAM_PERIPH_RECOVERY_INPROG) { ! error = ERESTART; ! break; ! } ! ! periph->flags |= ! CAM_PERIPH_RECOVERY_INPROG; ! ! /* decrement the number of retries */ ! retry = 1; ! ccb->ccb_h.retry_count--; ! ! /* ! * Check for removable media and ! * set load/eject flag ! * appropriately. ! */ ! if (SID_IS_REMOVABLE(&cgd.inq_data)) ! le = TRUE; ! else ! le = FALSE; ! ! /* ! * Attempt to start the drive up. ! * ! * Save the current ccb so it can ! * be restored and retried once the ! * drive is started up. ! */ ! bcopy(ccb, save_ccb, sizeof(*save_ccb)); ! ! scsi_start_stop(&ccb->csio, ! /*retries*/1, ! camperiphdone, ! MSG_SIMPLE_Q_TAG, ! /*start*/TRUE, ! /*load/eject*/le, ! /*immediate*/FALSE, ! SSD_FULL_SIZE, ! /*timeout*/50000); ! /* ! * Drop the priority to 0 so that ! * we are the first to execute. Also ! * freeze the queue after this command ! * is sent so that we can restore the ! * old csio and have it queued in the ! * proper order before we let normal ! * transactions go to the drive. ! */ ! ccb->ccb_h.pinfo.priority = 0; ! ccb->ccb_h.flags |= CAM_DEV_QFREEZE; ! ! /* ! * Save a pointer to the original ! * CCB in the new CCB. ! */ ! ccb->ccb_h.saved_ccb_ptr = save_ccb; ! ! error = ERESTART; ! } else if ((sense_flags & SF_RETRY_UA) != 0) { ! /* ! * XXX KDM this is a *horrible* ! * hack. ! */ ! error = scsi_interpret_sense(ccb, ! sense_flags, ! &relsim_flags, ! &openings, ! &timeout, ! err_action); ! } ! ! /* ! * Theoretically, this code should send a ! * test unit ready to the given device, and ! * if it returns and error, send a start ! * unit command. Since we don't yet have ! * the capability to do two-command error ! * recovery, just send a start unit. ! * XXX KDM fix this! ! */ ! else if (((err_action & SS_MASK) == SS_TURSTART) ! && save_ccb != NULL ! && ccb->ccb_h.retry_count > 0) { ! int le; ! ! /* ! * Only one error recovery action ! * at a time. See above. ! */ ! if (periph->flags & ! CAM_PERIPH_RECOVERY_INPROG) { ! error = ERESTART; ! break; ! } ! ! periph->flags |= ! CAM_PERIPH_RECOVERY_INPROG; ! ! /* decrement the number of retries */ ! retry = 1; ! ccb->ccb_h.retry_count--; ! ! /* ! * Check for removable media and ! * set load/eject flag ! * appropriately. ! */ ! if (SID_IS_REMOVABLE(&cgd.inq_data)) ! le = TRUE; ! else ! le = FALSE; ! ! /* ! * Attempt to start the drive up. ! * ! * Save the current ccb so it can ! * be restored and retried once the ! * drive is started up. ! */ ! bcopy(ccb, save_ccb, sizeof(*save_ccb)); ! ! scsi_start_stop(&ccb->csio, ! /*retries*/1, ! camperiphdone, ! MSG_SIMPLE_Q_TAG, ! /*start*/TRUE, ! /*load/eject*/le, ! /*immediate*/FALSE, ! SSD_FULL_SIZE, ! /*timeout*/50000); ! ! /* release the queue after .5 sec. */ ! relsim_flags = ! RELSIM_RELEASE_AFTER_TIMEOUT; ! timeout = 500; ! /* ! * Drop the priority to 0 so that ! * we are the first to execute. Also ! * freeze the queue after this command ! * is sent so that we can restore the ! * old csio and have it queued in the ! * proper order before we let normal ! * transactions go to the drive. ! */ ! ccb->ccb_h.pinfo.priority = 0; ! ccb->ccb_h.flags |= CAM_DEV_QFREEZE; ! ! /* ! * Save a pointer to the original ! * CCB in the new CCB. ! */ ! ccb->ccb_h.saved_ccb_ptr = save_ccb; ! ! error = ERESTART; ! } else { ! error = scsi_interpret_sense(ccb, ! sense_flags, ! &relsim_flags, ! &openings, ! &timeout, ! err_action); ! } ! } else if (ccb->csio.scsi_status == ! SCSI_STATUS_CHECK_COND ! && status != CAM_AUTOSENSE_FAIL) { ! /* no point in decrementing the retry count */ ! panic("cam_periph_error: scsi status of " ! "CHECK COND returned but no sense " ! "information is availible. " ! "Controller should have returned " ! "CAM_AUTOSENSE_FAILED"); ! /* NOTREACHED */ ! error = EIO; ! } else if (ccb->ccb_h.retry_count == 0) { ! /* ! * XXX KDM shouldn't there be a better ! * argument to return?? ! */ ! error = EIO; ! } else { ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) ! ccb->ccb_h.retry_count--; ! /* ! * If it was aborted with no ! * clue as to the reason, just ! * retry it again. ! */ ! error = ERESTART; ! } break; ! case SCSI_STATUS_QUEUE_FULL: { ! /* no decrement */ ! struct ccb_getdevstats cgds; /* ! * First off, find out what the current ! * transaction counts are. */ ! xpt_setup_ccb(&cgds.ccb_h, ! ccb->ccb_h.path, ! /*priority*/1); ! cgds.ccb_h.func_code = XPT_GDEV_STATS; ! xpt_action((union ccb *)&cgds); /* ! * If we were the only transaction active, treat ! * the QUEUE FULL as if it were a BUSY condition. */ ! if (cgds.dev_active != 0) { ! int total_openings; ! /* ! * Reduce the number of openings to ! * be 1 less than the amount it took ! * to get a queue full bounded by the ! * minimum allowed tag count for this ! * device. ! */ ! total_openings = ! cgds.dev_active+cgds.dev_openings; ! openings = cgds.dev_active; ! if (openings < cgds.mintags) ! openings = cgds.mintags; ! if (openings < total_openings) ! relsim_flags = RELSIM_ADJUST_OPENINGS; ! else { ! /* ! * Some devices report queue full for ! * temporary resource shortages. For ! * this reason, we allow a minimum ! * tag count to be entered via a ! * quirk entry to prevent the queue ! * count on these devices from falling ! * to a pessimisticly low value. We ! * still wait for the next successful ! * completion, however, before queueing ! * more transactions to the device. ! */ ! relsim_flags = ! RELSIM_RELEASE_AFTER_CMDCMPLT; ! } ! timeout = 0; ! error = ERESTART; ! break; ! } ! /* FALLTHROUGH */ } ! case SCSI_STATUS_BUSY: /* ! * Restart the queue after either another ! * command completes or a 1 second timeout. ! * If we have any retries left, that is. */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT ! | RELSIM_RELEASE_AFTER_CMDCMPLT; ! timeout = 1000; } else { ! error = EIO; } break; ! case SCSI_STATUS_RESERV_CONFLICT: ! error = EIO; break; default: ! error = EIO; ! break; } break; case CAM_REQ_CMP_ERR: case CAM_CMD_TIMEOUT: case CAM_UNEXP_BUSFREE: case CAM_UNCOR_PARITY: case CAM_DATA_RUN_ERR: /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ccb->ccb_h.retry_count--; error = ERESTART; } else { error = EIO; } break; --- 1173,1542 ---- } ! static int ! camperiphscsistatuserror(union ccb *ccb, cam_flags camflags, ! u_int32_t sense_flags, union ccb *save_ccb, ! int *openings, u_int32_t *relsim_flags, ! u_int32_t *timeout) { ! int error; ! switch (ccb->csio.scsi_status) { ! case SCSI_STATUS_OK: ! case SCSI_STATUS_COND_MET: ! case SCSI_STATUS_INTERMED: ! case SCSI_STATUS_INTERMED_COND_MET: error = 0; break; ! case SCSI_STATUS_CMD_TERMINATED: ! case SCSI_STATUS_CHECK_COND: ! error = camperiphscsisenseerror(ccb, ! camflags, ! sense_flags, ! save_ccb, ! openings, ! relsim_flags, ! timeout); ! break; ! case SCSI_STATUS_QUEUE_FULL: ! { ! /* no decrement */ ! struct ccb_getdevstats cgds; ! /* ! * First off, find out what the current ! * transaction counts are. ! */ ! xpt_setup_ccb(&cgds.ccb_h, ! ccb->ccb_h.path, ! /*priority*/1); ! cgds.ccb_h.func_code = XPT_GDEV_STATS; ! xpt_action((union ccb *)&cgds); ! /* ! * If we were the only transaction active, treat ! * the QUEUE FULL as if it were a BUSY condition. ! */ ! if (cgds.dev_active != 0) { ! int total_openings; + /* + * Reduce the number of openings to + * be 1 less than the amount it took + * to get a queue full bounded by the + * minimum allowed tag count for this + * device. + */ + total_openings = cgds.dev_active + cgds.dev_openings; + *openings = cgds.dev_active; + if (*openings < cgds.mintags) + *openings = cgds.mintags; + if (*openings < total_openings) + *relsim_flags = RELSIM_ADJUST_OPENINGS; + else { /* ! * Some devices report queue full for ! * temporary resource shortages. For ! * this reason, we allow a minimum ! * tag count to be entered via a ! * quirk entry to prevent the queue ! * count on these devices from falling ! * to a pessimisticly low value. We ! * still wait for the next successful ! * completion, however, before queueing ! * more transactions to the device. */ ! *relsim_flags = RELSIM_RELEASE_AFTER_CMDCMPLT; ! } ! *timeout = 0; ! error = ERESTART; ! break; ! } ! /* FALLTHROUGH */ ! } ! case SCSI_STATUS_BUSY: ! /* ! * Restart the queue after either another ! * command completes or a 1 second timeout. ! */ ! if (ccb->ccb_h.retry_count > 0) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT ! | RELSIM_RELEASE_AFTER_CMDCMPLT; ! *timeout = 1000; ! } else { ! error = EIO; ! } ! break; ! case SCSI_STATUS_RESERV_CONFLICT: ! error = EIO; ! break; ! default: ! error = EIO; ! break; ! } ! return (error); ! } ! static int ! camperiphscsisenseerror(union ccb *ccb, cam_flags camflags, ! u_int32_t sense_flags, union ccb *save_ccb, ! int *openings, u_int32_t *relsim_flags, ! u_int32_t *timeout) ! { ! struct cam_periph *periph; ! int error; ! periph = xpt_path_periph(ccb->ccb_h.path); ! if (periph->flags & CAM_PERIPH_RECOVERY_INPROG) { ! /* ! * If error recovery is already in progress, don't attempt ! * to process this error, but requeue it unconditionally ! * and attempt to process it once error recovery has ! * completed. This failed command is probably related to ! * the error that caused the currently active error recovery ! * action so our current recovery efforts should also ! * address this command. Be aware that the error recovery ! * code assumes that only one recovery action is in progress ! * on a particular peripheral instance at any given time ! * (e.g. only one saved CCB for error recovery) so it is ! * imperitive that we don't violate this assumption. ! */ ! error = ERESTART; ! } else { ! scsi_sense_action err_action; ! struct ccb_getdev cgd; ! const char *action_string; ! union ccb* print_ccb; ! /* A description of the error recovery action performed */ ! action_string = NULL; ! /* ! * The location of the orignal ccb ! * for sense printing purposes. ! */ ! print_ccb = ccb; ! /* ! * Grab the inquiry data for this device. ! */ ! xpt_setup_ccb(&cgd.ccb_h, ccb->ccb_h.path, /*priority*/ 1); ! cgd.ccb_h.func_code = XPT_GDEV_TYPE; ! xpt_action((union ccb *)&cgd); ! if ((ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) ! err_action = scsi_error_action(&ccb->csio, ! &cgd.inq_data, ! sense_flags); ! else if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) ! err_action = SS_REQSENSE; ! else ! err_action = SS_RETRY|SSQ_DECREMENT_COUNT|EIO; ! error = err_action & SS_ERRMASK; ! /* ! * If the recovery action will consume a retry, ! * make sure we actually have retries available. ! */ ! if ((err_action & SSQ_DECREMENT_COUNT) != 0) { ! if (ccb->ccb_h.retry_count > 0) ! ccb->ccb_h.retry_count--; ! else { ! action_string = "Retries Exhausted"; ! goto sense_error_done; ! } ! } ! if ((err_action & SS_MASK) >= SS_START) { ! /* ! * Do common portions of commands that ! * use recovery CCBs. ! */ ! if (save_ccb == NULL) { ! action_string = "No recovery CCB supplied"; ! goto sense_error_done; ! } ! bcopy(ccb, save_ccb, sizeof(*save_ccb)); ! print_ccb = save_ccb; ! periph->flags |= CAM_PERIPH_RECOVERY_INPROG; ! } ! switch (err_action & SS_MASK) { ! case SS_NOP: ! case SS_RETRY: ! action_string = "Retrying Command"; ! error = ERESTART; ! break; ! case SS_FAIL: ! action_string = "Unretryable error"; break; ! case SS_START: { ! int le; /* ! * Send a start unit command to the device, and ! * then retry the command. */ ! action_string = "Attempting to Start Unit"; /* ! * Check for removable media and set ! * load/eject flag appropriately. */ ! if (SID_IS_REMOVABLE(&cgd.inq_data)) ! le = TRUE; ! else ! le = FALSE; ! scsi_start_stop(&ccb->csio, ! /*retries*/1, ! camperiphdone, ! MSG_SIMPLE_Q_TAG, ! /*start*/TRUE, ! /*load/eject*/le, ! /*immediate*/FALSE, ! SSD_FULL_SIZE, ! /*timeout*/50000); ! break; } ! case SS_TUR: ! { /* ! * Send a Test Unit Ready to the device. ! * If the 'many' flag is set, we send 120 ! * test unit ready commands, one every half ! * second. Otherwise, we just send one TUR. ! * We only want to do this if the retry ! * count has not been exhausted. */ ! int retries; ! ! if ((err_action & SSQ_MANY) != 0) { ! action_string = "Polling device for readiness"; ! retries = 120; } else { ! action_string = "Testing device for readiness"; ! retries = 1; } + scsi_test_unit_ready(&ccb->csio, + retries, + camperiphdone, + MSG_SIMPLE_Q_TAG, + SSD_FULL_SIZE, + /*timeout*/5000); + + /* + * Accomplish our 500ms delay by deferring + * the release of our device queue appropriately. + */ + *relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; + *timeout = 500; break; ! } ! case SS_REQSENSE: ! { ! /* ! * Send a Request Sense to the device. We ! * assume that we are in a contingent allegiance ! * condition so we do not tag this request. ! */ ! scsi_request_sense(&ccb->csio, /*retries*/1, ! camperiphdone, ! &save_ccb->csio.sense_data, ! sizeof(save_ccb->csio.sense_data), ! CAM_TAG_ACTION_NONE, ! /*sense_len*/SSD_FULL_SIZE, ! /*timeout*/5000); break; + } default: ! panic("Unhandled error action %x\n", err_action); ! } ! ! if ((err_action & SS_MASK) >= SS_START) { ! /* ! * Drop the priority to 0 so that the recovery ! * CCB is the first to execute. Freeze the queue ! * after this command is sent so that we can ! * restore the old csio and have it queued in ! * the proper order before we release normal ! * transactions to the device. ! */ ! ccb->ccb_h.pinfo.priority = 0; ! ccb->ccb_h.flags |= CAM_DEV_QFREEZE; ! ccb->ccb_h.saved_ccb_ptr = save_ccb; ! error = ERESTART; ! } ! ! sense_error_done: ! if ((err_action & SSQ_PRINT_SENSE) != 0 ! && (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) { ! #if 0 ! scsi_sense_print(&print_ccb->csio); ! #endif ! cam_error_print(print_ccb, CAM_ESF_ALL, CAM_EPF_ALL); ! xpt_print_path(ccb->ccb_h.path); ! printf("%s\n", action_string); } + } + return (error); + } + + /* + * Generic error handler. Peripheral drivers usually filter + * out the errors that they handle in a unique mannor, then + * call this function. + */ + int + cam_periph_error(union ccb *ccb, cam_flags camflags, + u_int32_t sense_flags, union ccb *save_ccb) + { + const char *action_string; + cam_status status; + int frozen; + int error; + int openings; + u_int32_t relsim_flags; + u_int32_t timeout; + + action_string = NULL; + status = ccb->ccb_h.status; + frozen = (status & CAM_DEV_QFRZN) != 0; + status &= CAM_STATUS_MASK; + relsim_flags = 0; + + switch (status) { + case CAM_REQ_CMP: + error = 0; + break; + case CAM_SCSI_STATUS_ERROR: + error = camperiphscsistatuserror(ccb, + camflags, + sense_flags, + save_ccb, + &openings, + &relsim_flags, + &timeout); break; + case CAM_AUTOSENSE_FAIL: + xpt_print_path(ccb->ccb_h.path); + printf("AutoSense Failed\n"); case CAM_REQ_CMP_ERR: case CAM_CMD_TIMEOUT: case CAM_UNEXP_BUSFREE: case CAM_UNCOR_PARITY: case CAM_DATA_RUN_ERR: /* decrement the number of retries */ ! if (ccb->ccb_h.retry_count > 0) { ccb->ccb_h.retry_count--; error = ERESTART; } else { + action_string = "Retries Exausted"; error = EIO; } break; *************** *** 1587,1632 **** break; case CAM_SEL_TIMEOUT: { - /* - * XXX - * A single selection timeout should not be enough - * to invalidate a device. We should retry for multiple - * seconds assuming this isn't a probe. We'll probably - * need a special flag for that. - */ - #if 0 struct cam_path *newpath; /* Should we do more if we can't create the path?? */ if (xpt_create_path(&newpath, xpt_path_periph(ccb->ccb_h.path), xpt_path_path_id(ccb->ccb_h.path), xpt_path_target_id(ccb->ccb_h.path), CAM_LUN_WILDCARD) != CAM_REQ_CMP) break; /* * Let peripheral drivers know that this device has gone * away. */ xpt_async(AC_LOST_DEVICE, newpath, NULL); xpt_free_path(newpath); - #endif - if ((sense_flags & SF_RETRY_SELTO) != 0) { - retry = ccb->ccb_h.retry_count > 0; - if (retry) { - ccb->ccb_h.retry_count--; - error = ERESTART; - /* - * Wait half a second to give the device - * time to recover before we try again. - */ - relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; - timeout = 500; - } else { - error = ENXIO; - } - } else { - error = ENXIO; - } break; } case CAM_REQ_INVALID: --- 1548,1584 ---- break; case CAM_SEL_TIMEOUT: { struct cam_path *newpath; + if ((camflags & CAM_RETRY_SELTO) != 0) { + if (ccb->ccb_h.retry_count > 0) { + + ccb->ccb_h.retry_count--; + error = ERESTART; + + /* + * Wait a second to give the device + * time to recover before we try again. + */ + relsim_flags = RELSIM_RELEASE_AFTER_TIMEOUT; + timeout = 1000; + break; + } + } + error = ENXIO; /* Should we do more if we can't create the path?? */ if (xpt_create_path(&newpath, xpt_path_periph(ccb->ccb_h.path), xpt_path_path_id(ccb->ccb_h.path), xpt_path_target_id(ccb->ccb_h.path), CAM_LUN_WILDCARD) != CAM_REQ_CMP) break; + /* * Let peripheral drivers know that this device has gone * away. */ xpt_async(AC_LOST_DEVICE, newpath, NULL); xpt_free_path(newpath); break; } case CAM_REQ_INVALID: *************** *** 1634,1646 **** case CAM_DEV_NOT_THERE: case CAM_NO_HBA: case CAM_PROVIDE_FAIL: ! case CAM_REQ_TOO_BIG: error = EINVAL; break; case CAM_SCSI_BUS_RESET: ! case CAM_BDR_SENT: case CAM_REQUEUE_REQ: ! /* Unconditional requeue, dammit */ error = ERESTART; break; case CAM_RESRC_UNAVAIL: --- 1586,1607 ---- case CAM_DEV_NOT_THERE: case CAM_NO_HBA: case CAM_PROVIDE_FAIL: ! case CAM_REQ_TOO_BIG: error = EINVAL; break; case CAM_SCSI_BUS_RESET: ! case CAM_BDR_SENT: ! /* ! * Commands that repeatedly timeout and cause these ! * kinds of error recovery actions, should return ! * CAM_CMD_TIMEOUT, which allows us to safely assume ! * that this command was an innocent bystander to ! * these events and should be unconditionally ! * retried. ! */ ! /* FALLTHROUGH */ case CAM_REQUEUE_REQ: ! /* Unconditional requeue */ error = ERESTART; break; case CAM_RESRC_UNAVAIL: *************** *** 1648,1660 **** /* timeout??? */ default: /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ccb->ccb_h.retry_count--; error = ERESTART; } else { - /* Check the sense codes */ error = EIO; } break; } --- 1609,1620 ---- /* timeout??? */ default: /* decrement the number of retries */ ! if (ccb->ccb_h.retry_count > 0) { ccb->ccb_h.retry_count--; error = ERESTART; } else { error = EIO; + action_string = "Retries Exhausted"; } break; } *************** *** 1664,1681 **** if (frozen != 0) ccb->ccb_h.status &= ~CAM_DEV_QFRZN; ! if (error == ERESTART) xpt_action(ccb); ! if (frozen != 0) { cam_release_devq(ccb->ccb_h.path, relsim_flags, openings, timeout, /*getcount_only*/0); } } - return (error); } --- 1624,1653 ---- if (frozen != 0) ccb->ccb_h.status &= ~CAM_DEV_QFRZN; ! if (error == ERESTART) { ! action_string = "Retrying Command"; xpt_action(ccb); + } ! if (frozen != 0) cam_release_devq(ccb->ccb_h.path, relsim_flags, openings, timeout, /*getcount_only*/0); + } + + if (error != 0 && bootverbose) { + + if (action_string == NULL) + action_string = "Unretryable Error"; + if (error != ERESTART) { + xpt_print_path(ccb->ccb_h.path); + printf("error %d\n", error); } + xpt_print_path(ccb->ccb_h.path); + printf("%s\n", action_string); } return (error); } *** src/sys/cam/cam_xpt.c.orig --- src/sys/cam/cam_xpt.c *************** *** 40,45 **** --- 40,46 ---- #include #include #include + #include #ifdef PC98 #include /* geometry translation */ *************** *** 122,128 **** 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; u_int8_t inq_flags; /* * Current settings for inquiry flags. * This allows us to override settings --- 123,135 ---- struct cam_periph *owner; /* Peripheral driver's ownership tag */ struct xpt_quirk_entry *quirk; /* Oddities about this device */ /* Storage for the inquiry 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,137 **** */ u_int8_t queue_flags; /* Queue flags from the control page */ u_int8_t serial_num_len; ! u_int8_t *serial_num; u_int32_t qfrozen_cnt; u_int32_t flags; #define CAM_DEV_UNCONFIGURED 0x01 --- 138,144 ---- */ u_int8_t queue_flags; /* Queue flags from the control page */ u_int8_t serial_num_len; ! u_int8_t *serial_num; u_int32_t qfrozen_cnt; u_int32_t flags; #define CAM_DEV_UNCONFIGURED 0x01 *************** *** 719,729 **** 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); static dev_match_ret xptdevicematch(struct dev_match_pattern *patterns, ! int num_patterns, struct cam_ed *device); static dev_match_ret xptperiphmatch(struct dev_match_pattern *patterns, ! int num_patterns, struct cam_periph *periph); static xpt_busfunc_t xptedtbusfunc; static xpt_targetfunc_t xptedttargetfunc; --- 726,737 ---- u_int32_t code, cam_path *path); #endif static dev_match_ret xptbusmatch(struct dev_match_pattern *patterns, ! u_int num_patterns, struct cam_eb *bus); static dev_match_ret xptdevicematch(struct dev_match_pattern *patterns, ! u_int num_patterns, ! struct cam_ed *device); static dev_match_ret xptperiphmatch(struct dev_match_pattern *patterns, ! u_int num_patterns, struct cam_periph *periph); static xpt_busfunc_t xptedtbusfunc; static xpt_targetfunc_t xptedttargetfunc; *************** *** 777,782 **** --- 785,793 ---- 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); *************** *** 1130,1137 **** struct cam_periph *periph; struct periph_driver **p_drv; char *name; ! int unit; ! int cur_generation; int base_periph_found; int splbreaknum; int s; --- 1141,1148 ---- struct cam_periph *periph; struct periph_driver **p_drv; char *name; ! u_int unit; ! u_int cur_generation; int base_periph_found; int splbreaknum; int s; *************** *** 1465,1473 **** --- 1476,1596 ---- } + #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) + { int s; u_int mb; struct cam_path *path; *************** *** 1568,1576 **** splx(s); } static dev_match_ret ! xptbusmatch(struct dev_match_pattern *patterns, int num_patterns, struct cam_eb *bus) { dev_match_ret retval; --- 1691,1700 ---- splx(s); } + #endif /* CAM_NEW_TRAN_CODE */ static dev_match_ret ! xptbusmatch(struct dev_match_pattern *patterns, u_int num_patterns, struct cam_eb *bus) { dev_match_ret retval; *************** *** 1682,1688 **** } static dev_match_ret ! xptdevicematch(struct dev_match_pattern *patterns, int num_patterns, struct cam_ed *device) { dev_match_ret retval; --- 1806,1812 ---- } static dev_match_ret ! xptdevicematch(struct dev_match_pattern *patterns, u_int num_patterns, struct cam_ed *device) { dev_match_ret retval; *************** *** 1798,1804 **** * Match a single peripheral against any number of match patterns. */ static dev_match_ret ! xptperiphmatch(struct dev_match_pattern *patterns, int num_patterns, struct cam_periph *periph) { dev_match_ret retval; --- 1922,1928 ---- * Match a single peripheral against any number of match patterns. */ static dev_match_ret ! xptperiphmatch(struct dev_match_pattern *patterns, u_int num_patterns, struct cam_periph *periph) { dev_match_ret retval; *************** *** 2779,2784 **** --- 2903,2911 ---- 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; *************** *** 2802,2808 **** --- 2929,2940 ---- * 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) { *************** *** 3024,3030 **** struct cam_periph *nperiph; struct periph_list *periph_head; struct ccb_getdevlist *cgdl; ! int i; int s; struct cam_ed *device; int found; --- 3156,3162 ---- struct cam_periph *nperiph; struct periph_list *periph_head; struct ccb_getdevlist *cgdl; ! u_int i; int s; struct cam_ed *device; int found; *************** *** 3116,3122 **** if (cdm->pos.position_type != CAM_DEV_POS_NONE) position_type = cdm->pos.position_type; else { ! int i; position_type = CAM_DEV_POS_NONE; --- 3248,3254 ---- if (cdm->pos.position_type != CAM_DEV_POS_NONE) position_type = cdm->pos.position_type; else { ! u_int i; position_type = CAM_DEV_POS_NONE; *************** *** 3981,3986 **** --- 4113,4156 ---- } } + 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) { *************** *** 4116,4122 **** 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_release_path(&path); } return (CAM_SUCCESS); --- 4286,4292 ---- 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, &path, &cpi); xpt_release_path(&path); } return (CAM_SUCCESS); *************** *** 4694,4699 **** --- 4864,4872 ---- 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; *************** *** 4770,4775 **** --- 4943,4959 ---- 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); } *************** *** 4965,4974 **** 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; --- 5149,5154 ---- *************** *** 4991,5001 **** 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; --- 5171,5176 ---- *************** *** 5088,5097 **** 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; --- 5263,5268 ---- *************** *** 5469,5479 **** --- 5640,5658 ---- 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); } *************** *** 5551,5556 **** --- 5730,5738 ---- 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; *************** *** 5789,5794 **** --- 5971,6349 ---- 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) *************** *** 5973,5978 **** --- 6528,6536 ---- } } + + #endif /* CAM_NEW_TRAN_CODE */ + static void xpt_toggle_tags(struct cam_path *path) { *************** *** 5992,6002 **** --- 6550,6573 ---- 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); } *************** *** 6112,6118 **** static void xpt_config(void *arg) { ! /* Now that interrupts are enabled, go find our devices */ #ifdef CAMDEBUG /* Setup debugging flags and path */ --- 6683,6691 ---- static void xpt_config(void *arg) { ! /* ! * Now that interrupts are enabled, go find our devices ! */ #ifdef CAMDEBUG /* Setup debugging flags and path */ *************** *** 6253,6258 **** --- 6826,6837 ---- 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; *************** *** 6331,6337 **** ccb_h->path->bus->sim->devq->send_openings++; splx(s); ! if ((dev->flags & CAM_DEV_REL_ON_COMPLETE) != 0 || ((dev->flags & CAM_DEV_REL_ON_QUEUE_EMPTY) != 0 && (dev->ccbq.dev_active == 0))) { --- 6910,6917 ---- ccb_h->path->bus->sim->devq->send_openings++; splx(s); ! 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))) { *** src/sys/cam/cam_xpt.h.orig --- src/sys/cam/cam_xpt.h *************** *** 62,67 **** --- 62,69 ---- 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); *** src/sys/cam/scsi/scsi_all.c.orig --- src/sys/cam/scsi/scsi_all.c *************** *** 1,7 **** /* * Implementation of Utility functions for all SCSI device types. * ! * Copyright (c) 1997, 1998 Justin T. Gibbs. * Copyright (c) 1997, 1998 Kenneth D. Merry. * All rights reserved. * --- 1,7 ---- /* * Implementation of Utility functions for all SCSI device types. * ! * Copyright (c) 1997, 1998, 1999 Justin T. Gibbs. * Copyright (c) 1997, 1998 Kenneth D. Merry. * All rights reserved. * *************** *** 26,32 **** * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ! * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.20 2001/02/24 19:24:36 gibbs Exp $ */ #include --- 26,32 ---- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ! * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.17 2000/10/30 08:08:00 phk Exp $ */ #include *************** *** 35,43 **** --- 35,45 ---- #include #include + #include #else #include #include + #include #include #endif *************** *** 45,50 **** --- 47,53 ---- #include #include #include + #include #ifndef _KERNEL #include *************** *** 58,82 **** #define EJUSTRETURN -2 /* don't modify regs, just return */ #endif /* !_KERNEL */ ! const char *scsi_sense_key_text[] = ! { ! "NO SENSE", ! "RECOVERED ERROR", ! "NOT READY", ! "MEDIUM ERROR", ! "HARDWARE FAILURE", ! "ILLEGAL REQUEST", ! "UNIT ATTENTION", ! "DATA PROTECT", ! "BLANK CHECK", ! "Vendor Specific", ! "COPY ABORTED", ! "ABORTED COMMAND", ! "EQUAL", ! "VOLUME OVERFLOW", ! "MISCOMPARE", ! "RESERVED" ! }; #if !defined(SCSI_NO_OP_STRINGS) --- 61,72 ---- #define EJUSTRETURN -2 /* don't modify regs, just return */ #endif /* !_KERNEL */ ! static int ascentrycomp(const void *key, const void *member); ! static int senseentrycomp(const void *key, const void *member); ! static void fetchtableentries(int sense_key, int asc, int ascq, ! struct scsi_inquiry_data *, ! const struct sense_key_table_entry **, ! const struct asc_table_entry **); #if !defined(SCSI_NO_OP_STRINGS) *************** *** 95,104 **** #define ALL 0xFFF - /* - * WARNING: You must update the num_ops field below for this quirk table - * entry if you add more entries. - */ static struct op_table_entry plextor_cd_ops[] = { {0xD8, R, "CD-DA READ"} }; --- 85,90 ---- *************** *** 115,121 **** * feel free to change this quirk entry. */ {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"}, ! 1, /* number of vendor-specific opcodes for this entry */ plextor_cd_ops } }; --- 101,107 ---- * feel free to change this quirk entry. */ {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"}, ! sizeof(plextor_cd_ops)/sizeof(struct op_table_entry), plextor_cd_ops } }; *************** *** 701,727 **** #include - #if !defined(SCSI_NO_SENSE_STRINGS) #define SST(asc, ascq, action, desc) \ asc, ascq, action, desc #else #define SST(asc, ascq, action, desc) \ ! asc, ascq, action #endif static const char quantum[] = "QUANTUM"; ! /* ! * WARNING: You must update the num_ascs field below for this quirk table ! * entry if you add more entries. ! */ static struct asc_table_entry quantum_fireball_entries[] = { {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, "Logical unit not ready, initializing cmd. required")} }; ! static struct scsi_sense_quirk_entry asc_quirk_table[] = { { /* * The Quantum Fireball ST and SE like to return 0x04 0x0b when --- 687,734 ---- #include #if !defined(SCSI_NO_SENSE_STRINGS) #define SST(asc, ascq, action, desc) \ asc, ascq, action, desc #else + const char empty_string[] = ""; + #define SST(asc, ascq, action, desc) \ ! asc, ascq, action, empty_string #endif static const char quantum[] = "QUANTUM"; ! const struct sense_key_table_entry sense_key_table[] = ! { ! { SSD_KEY_NO_SENSE, SS_NOP, "NO SENSE" }, ! { SSD_KEY_RECOVERED_ERROR, SS_NOP|SSQ_PRINT_SENSE, "RECOVERED ERROR" }, ! { ! SSD_KEY_NOT_READY, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY, ! "NOT READY" ! }, ! { SSD_KEY_MEDIUM_ERROR, SS_RDEF, "MEDIUM ERROR" }, ! { SSD_KEY_HARDWARE_ERROR, SS_RDEF, "HARDWARE FAILURE" }, ! { SSD_KEY_ILLEGAL_REQUEST, SS_FATAL|EINVAL, "ILLEGAL REQUEST" }, ! { SSD_KEY_UNIT_ATTENTION, SS_FATAL|ENXIO, "UNIT ATTENTION" }, ! { SSD_KEY_Vendor_Specific, SS_FATAL|EIO, "Vendor Specific" }, ! { SSD_KEY_COPY_ABORTED, SS_FATAL|EIO, "COPY ABORTED" }, ! { SSD_KEY_ABORTED_COMMAND, SS_RDEF, "ABORTED COMMAND" }, ! { SSD_KEY_EQUAL, SS_NOP, "EQUAL" }, ! { SSD_KEY_VOLUME_OVERFLOW, SS_FATAL|EIO, "VOLUME OVERFLOW" }, ! { SSD_KEY_MISCOMPARE, SS_NOP, "MISCOMPARE" }, ! { SSD_KEY_RESERVED, SS_FATAL|EIO, "RESERVED" } ! }; ! ! const int sense_key_table_size = ! sizeof(sense_key_table)/sizeof(sense_key_table[0]); ! static struct asc_table_entry quantum_fireball_entries[] = { {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, "Logical unit not ready, initializing cmd. required")} }; ! static struct scsi_sense_quirk_entry sense_quirk_table[] = { { /* * The Quantum Fireball ST and SE like to return 0x04 0x0b when *************** *** 730,741 **** * hardware manual for these drives. */ {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"}, ! 1, /* number of vendor-specific sense codes for this entry */ quantum_fireball_entries } }; ! static struct asc_table_entry asc_text[] = { /* * From File: ASC-NUM.TXT * SCSI ASC/ASCQ Assignments --- 737,753 ---- * hardware manual for these drives. */ {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"}, ! /*num_sense_keys*/0, ! sizeof(quantum_fireball_entries)/sizeof(struct asc_table_entry), ! /*sense key entries*/NULL, quantum_fireball_entries } }; ! const int sense_quirk_table_size = ! sizeof(sense_quirk_table)/sizeof(sense_quirk_table[0]); ! ! static struct asc_table_entry asc_table[] = { /* * From File: ASC-NUM.TXT * SCSI ASC/ASCQ Assignments *************** *** 756,798 **** * . . . . E - ENCLOSURE SERVICES DEVICE (SES) * DTLPWRSOMCAE ASC ASCQ Action Description * ------------ ---- ---- ------ -----------------------------------*/ ! /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NEPDEF, "No additional sense information") }, ! /* T S */{SST(0x00, 0x01, SS_DEF, "Filemark detected") }, ! /* T S */{SST(0x00, 0x02, SS_DEF, "End-of-partition/medium detected") }, ! /* T */{SST(0x00, 0x03, SS_DEF, "Setmark detected") }, ! /* T S */{SST(0x00, 0x04, SS_DEF, "Beginning-of-partition/medium detected") }, ! /* T S */{SST(0x00, 0x05, SS_DEF, "End-of-data detected") }, ! /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_DEF, "I/O process terminated") }, ! /* R */{SST(0x00, 0x11, SS_NEDEF|EBUSY, "Audio play operation in progress") }, ! /* R */{SST(0x00, 0x12, SS_NEDEF, "Audio play operation paused") }, ! /* R */{SST(0x00, 0x13, SS_NEDEF, "Audio play operation successfully completed") }, ! /* R */{SST(0x00, 0x14, SS_DEF, "Audio play operation stopped due to error") }, ! /* R */{SST(0x00, 0x15, SS_DEF, "No current audio status to return") }, ! /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_NEDEF|EBUSY, "Operation in progress") }, ! /* DTL WRSOM AE */{SST(0x00, 0x17, SS_DEF, "Cleaning requested") }, ! /* D W O */{SST(0x01, 0x00, SS_DEF, "No index/sector signal") }, ! /* D WR OM */{SST(0x02, 0x00, SS_DEF, "No seek complete") }, ! /* DTL W SO */{SST(0x03, 0x00, SS_DEF, "Peripheral device write fault") }, ! /* T */{SST(0x03, 0x01, SS_DEF, "No write current") }, ! /* T */{SST(0x03, 0x02, SS_DEF, "Excessive write errors") }, /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO, "Logical unit not ready, cause not reportable") }, --- 768,810 ---- * . . . . E - ENCLOSURE SERVICES DEVICE (SES) * DTLPWRSOMCAE ASC ASCQ Action Description * ------------ ---- ---- ------ -----------------------------------*/ ! /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NOP, "No additional sense information") }, ! /* T S */{SST(0x00, 0x01, SS_RDEF, "Filemark detected") }, ! /* T S */{SST(0x00, 0x02, SS_RDEF, "End-of-partition/medium detected") }, ! /* T */{SST(0x00, 0x03, SS_RDEF, "Setmark detected") }, ! /* T S */{SST(0x00, 0x04, SS_RDEF, "Beginning-of-partition/medium detected") }, ! /* T S */{SST(0x00, 0x05, SS_RDEF, "End-of-data detected") }, ! /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_RDEF, "I/O process terminated") }, ! /* R */{SST(0x00, 0x11, SS_FATAL|EBUSY, "Audio play operation in progress") }, ! /* R */{SST(0x00, 0x12, SS_NOP, "Audio play operation paused") }, ! /* R */{SST(0x00, 0x13, SS_NOP, "Audio play operation successfully completed") }, ! /* R */{SST(0x00, 0x14, SS_RDEF, "Audio play operation stopped due to error") }, ! /* R */{SST(0x00, 0x15, SS_NOP, "No current audio status to return") }, ! /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_FATAL|EBUSY, "Operation in progress") }, ! /* DTL WRSOM AE */{SST(0x00, 0x17, SS_RDEF, "Cleaning requested") }, ! /* D W O */{SST(0x01, 0x00, SS_RDEF, "No index/sector signal") }, ! /* D WR OM */{SST(0x02, 0x00, SS_RDEF, "No seek complete") }, ! /* DTL W SO */{SST(0x03, 0x00, SS_RDEF, "Peripheral device write fault") }, ! /* T */{SST(0x03, 0x01, SS_RDEF, "No write current") }, ! /* T */{SST(0x03, 0x02, SS_RDEF, "Excessive write errors") }, /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO, "Logical unit not ready, cause not reportable") }, *************** *** 800,1553 **** "Logical unit is in process of becoming ready") }, /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO, "Logical unit not ready, initializing cmd. required") }, ! /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_NEDEF|ENXIO, "Logical unit not ready, manual intervention required")}, ! /* DTL O */{SST(0x04, 0x04, SS_NEDEF|EBUSY, "Logical unit not ready, format in progress") }, ! /* DT W OMCA */{SST(0x04, 0x05, SS_NEDEF|EBUSY, "Logical unit not ready, rebuild in progress") }, ! /* DT W OMCA */{SST(0x04, 0x06, SS_NEDEF|EBUSY, "Logical unit not ready, recalculation in progress") }, ! /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_NEDEF|EBUSY, "Logical unit not ready, operation in progress") }, ! /* R */{SST(0x04, 0x08, SS_NEDEF|EBUSY, "Logical unit not ready, long write in progress") }, ! /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_DEF, "Logical unit does not respond to selection") }, ! /* D WR OM */{SST(0x06, 0x00, SS_DEF, "No reference position found") }, ! /* DTL WRSOM */{SST(0x07, 0x00, SS_DEF, "Multiple peripheral devices selected") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_DEF, "Logical unit communication failure") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_DEF, "Logical unit communication time-out") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_DEF, "Logical unit communication parity error") }, ! /* DT R OM */{SST(0x08, 0x03, SS_DEF, "Logical unit communication crc error (ultra-dma/32)")}, ! /* DT WR O */{SST(0x09, 0x00, SS_DEF, "Track following error") }, ! /* WR O */{SST(0x09, 0x01, SS_DEF, "Tracking servo failure") }, ! /* WR O */{SST(0x09, 0x02, SS_DEF, "Focus servo failure") }, ! /* WR O */{SST(0x09, 0x03, SS_DEF, "Spindle servo failure") }, ! /* DT WR O */{SST(0x09, 0x04, SS_DEF, "Head select fault") }, ! /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_NEDEF|ENOSPC, "Error log overflow") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_DEF, "Warning") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_DEF, "Specified temperature exceeded") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_DEF, "Enclosure degraded") }, ! /* T RS */{SST(0x0C, 0x00, SS_DEF, "Write error") }, ! /* D W O */{SST(0x0C, 0x01, SS_NEDEF, "Write error - recovered with auto reallocation") }, ! /* D W O */{SST(0x0C, 0x02, SS_DEF, "Write error - auto reallocation failed") }, ! /* D W O */{SST(0x0C, 0x03, SS_DEF, "Write error - recommend reassignment") }, ! /* DT W O */{SST(0x0C, 0x04, SS_NEPDEF, "Compression check miscompare error") }, ! /* DT W O */{SST(0x0C, 0x05, SS_DEF, "Data expansion occurred during compression") }, ! /* DT W O */{SST(0x0C, 0x06, SS_DEF, "Block not compressible") }, ! /* R */{SST(0x0C, 0x07, SS_DEF, "Write error - recovery needed") }, ! /* R */{SST(0x0C, 0x08, SS_DEF, "Write error - recovery failed") }, ! /* R */{SST(0x0C, 0x09, SS_DEF, "Write error - loss of streaming") }, ! /* R */{SST(0x0C, 0x0A, SS_DEF, "Write error - padding blocks added") }, ! /* D W O */{SST(0x10, 0x00, SS_DEF, "ID CRC or ECC error") }, ! /* DT WRSO */{SST(0x11, 0x00, SS_DEF, "Unrecovered read error") }, ! /* DT W SO */{SST(0x11, 0x01, SS_DEF, "Read retries exhausted") }, ! /* DT W SO */{SST(0x11, 0x02, SS_DEF, "Error too long to correct") }, ! /* DT W SO */{SST(0x11, 0x03, SS_DEF, "Multiple read errors") }, ! /* D W O */{SST(0x11, 0x04, SS_DEF, "Unrecovered read error - auto reallocate failed") }, ! /* WR O */{SST(0x11, 0x05, SS_DEF, "L-EC uncorrectable error") }, ! /* WR O */{SST(0x11, 0x06, SS_DEF, "CIRC unrecovered error") }, ! /* W O */{SST(0x11, 0x07, SS_DEF, "Data re-synchronization error") }, ! /* T */{SST(0x11, 0x08, SS_DEF, "Incomplete block read") }, ! /* T */{SST(0x11, 0x09, SS_DEF, "No gap found") }, ! /* DT O */{SST(0x11, 0x0A, SS_DEF, "Miscorrected error") }, ! /* D W O */{SST(0x11, 0x0B, SS_DEF, "Unrecovered read error - recommend reassignment") }, ! /* D W O */{SST(0x11, 0x0C, SS_DEF, "Unrecovered read error - recommend rewrite the data")}, ! /* DT WR O */{SST(0x11, 0x0D, SS_DEF, "De-compression CRC error") }, ! /* DT WR O */{SST(0x11, 0x0E, SS_DEF, "Cannot decompress using declared algorithm") }, ! /* R */{SST(0x11, 0x0F, SS_DEF, "Error reading UPC/EAN number") }, ! /* R */{SST(0x11, 0x10, SS_DEF, "Error reading ISRC number") }, ! /* R */{SST(0x11, 0x11, SS_DEF, "Read error - loss of streaming") }, ! /* D W O */{SST(0x12, 0x00, SS_DEF, "Address mark not found for id field") }, ! /* D W O */{SST(0x13, 0x00, SS_DEF, "Address mark not found for data field") }, ! /* DTL WRSO */{SST(0x14, 0x00, SS_DEF, "Recorded entity not found") }, ! /* DT WR O */{SST(0x14, 0x01, SS_DEF, "Record not found") }, ! /* T */{SST(0x14, 0x02, SS_DEF, "Filemark or setmark not found") }, ! /* T */{SST(0x14, 0x03, SS_DEF, "End-of-data not found") }, ! /* T */{SST(0x14, 0x04, SS_DEF, "Block sequence error") }, ! /* DT W O */{SST(0x14, 0x05, SS_DEF, "Record not found - recommend reassignment") }, ! /* DT W O */{SST(0x14, 0x06, SS_DEF, "Record not found - data auto-reallocated") }, ! /* DTL WRSOM */{SST(0x15, 0x00, SS_DEF, "Random positioning error") }, ! /* DTL WRSOM */{SST(0x15, 0x01, SS_DEF, "Mechanical positioning error") }, ! /* DT WR O */{SST(0x15, 0x02, SS_DEF, "Positioning error detected by read of medium") }, ! /* D W O */{SST(0x16, 0x00, SS_DEF, "Data synchronization mark error") }, ! /* D W O */{SST(0x16, 0x01, SS_DEF, "Data sync error - data rewritten") }, ! /* D W O */{SST(0x16, 0x02, SS_DEF, "Data sync error - recommend rewrite") }, ! /* D W O */{SST(0x16, 0x03, SS_NEDEF, "Data sync error - data auto-reallocated") }, ! /* D W O */{SST(0x16, 0x04, SS_DEF, "Data sync error - recommend reassignment") }, ! /* DT WRSO */{SST(0x17, 0x00, SS_NEDEF, "Recovered data with no error correction applied") }, ! /* DT WRSO */{SST(0x17, 0x01, SS_NEDEF, "Recovered data with retries") }, ! /* DT WR O */{SST(0x17, 0x02, SS_NEDEF, "Recovered data with positive head offset") }, ! /* DT WR O */{SST(0x17, 0x03, SS_NEDEF, "Recovered data with negative head offset") }, ! /* WR O */{SST(0x17, 0x04, SS_NEDEF, "Recovered data with retries and/or CIRC applied") }, ! /* D WR O */{SST(0x17, 0x05, SS_NEDEF, "Recovered data using previous sector id") }, ! /* D W O */{SST(0x17, 0x06, SS_NEDEF, "Recovered data without ECC - data auto-reallocated") }, ! /* D W O */{SST(0x17, 0x07, SS_NEDEF, "Recovered data without ECC - recommend reassignment")}, ! /* D W O */{SST(0x17, 0x08, SS_NEDEF, "Recovered data without ECC - recommend rewrite") }, ! /* D W O */{SST(0x17, 0x09, SS_NEDEF, "Recovered data without ECC - data rewritten") }, ! /* D W O */{SST(0x18, 0x00, SS_NEDEF, "Recovered data with error correction applied") }, ! /* D WR O */{SST(0x18, 0x01, SS_NEDEF, "Recovered data with error corr. & retries applied") }, ! /* D WR O */{SST(0x18, 0x02, SS_NEDEF, "Recovered data - data auto-reallocated") }, ! /* R */{SST(0x18, 0x03, SS_NEDEF, "Recovered data with CIRC") }, ! /* R */{SST(0x18, 0x04, SS_NEDEF, "Recovered data with L-EC") }, ! /* D WR O */{SST(0x18, 0x05, SS_NEDEF, "Recovered data - recommend reassignment") }, ! /* D WR O */{SST(0x18, 0x06, SS_NEDEF, "Recovered data - recommend rewrite") }, ! /* D W O */{SST(0x18, 0x07, SS_NEDEF, "Recovered data with ECC - data rewritten") }, ! /* D O */{SST(0x19, 0x00, SS_DEF, "Defect list error") }, ! /* D O */{SST(0x19, 0x01, SS_DEF, "Defect list not available") }, ! /* D O */{SST(0x19, 0x02, SS_DEF, "Defect list error in primary list") }, ! /* D O */{SST(0x19, 0x03, SS_DEF, "Defect list error in grown list") }, ! /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_DEF, "Parameter list length error") }, ! /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_DEF, "Synchronous data transfer error") }, ! /* D O */{SST(0x1C, 0x00, SS_DEF, "Defect list not found") }, ! /* D O */{SST(0x1C, 0x01, SS_DEF, "Primary defect list not found") }, ! /* D O */{SST(0x1C, 0x02, SS_DEF, "Grown defect list not found") }, ! /* D W O */{SST(0x1D, 0x00, SS_NEPDEF, "Miscompare during verify operation" )}, ! /* D W O */{SST(0x1E, 0x00, SS_NEDEF, "Recovered id with ecc correction") }, ! /* D O */{SST(0x1F, 0x00, SS_DEF, "Partial defect list transfer") }, ! /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_DEF, "Invalid command operation code") }, ! /* DT WR OM */{SST(0x21, 0x00, SS_DEF, "Logical block address out of range" )}, ! /* DT WR OM */{SST(0x21, 0x01, SS_DEF, "Invalid element address") }, ! /* D */{SST(0x22, 0x00, SS_DEF, "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */ ! /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_NEDEF|EINVAL, "Invalid field in CDB") }, ! /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_NEDEF|ENXIO, "Logical unit not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_NEDEF|EINVAL, "Invalid field in parameter list") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_NEDEF|EINVAL, "Parameter not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_NEDEF|EINVAL, "Parameter value invalid") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_DEF, "Threshold parameters not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_DEF, "Invalid release of active persistent reservation") }, ! /* DT W O */{SST(0x27, 0x00, SS_NEDEF|EACCES, "Write protected") }, ! /* DT W O */{SST(0x27, 0x01, SS_NEDEF|EACCES, "Hardware write protected") }, ! /* DT W O */{SST(0x27, 0x02, SS_NEDEF|EACCES, "Logical unit software write protected") }, ! /* T */{SST(0x27, 0x03, SS_NEDEF|EACCES, "Associated write protect") }, ! /* T */{SST(0x27, 0x04, SS_NEDEF|EACCES, "Persistent write protect") }, ! /* T */{SST(0x27, 0x05, SS_NEDEF|EACCES, "Permanent write protect") }, ! /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_NEDEF|ENXIO, "Not ready to ready change, medium may have changed") }, ! /* DT WR OM */{SST(0x28, 0x01, SS_DEF, "Import or export element accessed") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_NEDEF|ENXIO, "Power on, reset, or bus device reset occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_DEF, "Power on occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_DEF, "Scsi bus reset occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_DEF, "Bus device reset function occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_DEF, "Device internal reset") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_DEF, "Transceiver mode changed to single-ended") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_DEF, "Transceiver mode changed to LVD") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_DEF, "Parameters changed") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_DEF, "Mode parameters changed") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_DEF, "Log parameters changed") }, ! /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_DEF, "Reservations preempted") }, ! /* DTLPWRSO C */{SST(0x2B, 0x00, SS_DEF, "Copy cannot execute since host cannot disconnect") }, ! /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_DEF, "Command sequence error") }, ! /* S */{SST(0x2C, 0x01, SS_DEF, "Too many windows specified") }, ! /* S */{SST(0x2C, 0x02, SS_DEF, "Invalid combination of windows specified") }, ! /* R */{SST(0x2C, 0x03, SS_DEF, "Current program area is not empty") }, ! /* R */{SST(0x2C, 0x04, SS_DEF, "Current program area is empty") }, ! /* T */{SST(0x2D, 0x00, SS_DEF, "Overwrite error on update in place") }, ! /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_DEF, "Commands cleared by another initiator") }, ! /* DT WR OM */{SST(0x30, 0x00, SS_DEF, "Incompatible medium installed") }, ! /* DT WR O */{SST(0x30, 0x01, SS_DEF, "Cannot read medium - unknown format") }, ! /* DT WR O */{SST(0x30, 0x02, SS_DEF, "Cannot read medium - incompatible format") }, ! /* DT */{SST(0x30, 0x03, SS_DEF, "Cleaning cartridge installed") }, ! /* DT WR O */{SST(0x30, 0x04, SS_DEF, "Cannot write medium - unknown format") }, ! /* DT WR O */{SST(0x30, 0x05, SS_DEF, "Cannot write medium - incompatible format") }, ! /* DT W O */{SST(0x30, 0x06, SS_DEF, "Cannot format medium - incompatible medium") }, ! /* DTL WRSOM AE */{SST(0x30, 0x07, SS_DEF, "Cleaning failure") }, ! /* R */{SST(0x30, 0x08, SS_DEF, "Cannot write - application code mismatch") }, ! /* R */{SST(0x30, 0x09, SS_DEF, "Current session not fixated for append") }, ! /* DT WR O */{SST(0x31, 0x00, SS_DEF, "Medium format corrupted") }, ! /* D L R O */{SST(0x31, 0x01, SS_DEF, "Format command failed") }, ! /* D W O */{SST(0x32, 0x00, SS_DEF, "No defect spare location available") }, ! /* D W O */{SST(0x32, 0x01, SS_DEF, "Defect list update failure") }, ! /* T */{SST(0x33, 0x00, SS_DEF, "Tape length error") }, ! /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_DEF, "Enclosure failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_DEF, "Enclosure services failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_DEF, "Unsupported enclosure function") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_DEF, "Enclosure services unavailable") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_DEF, "Enclosure services transfer failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_DEF, "Enclosure services transfer refused") }, ! /* L */{SST(0x36, 0x00, SS_DEF, "Ribbon, ink, or toner failure") }, ! /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_DEF, "Rounded parameter") }, ! /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_DEF, "Saving parameters not supported") }, ! /* DTL WRSOM */{SST(0x3A, 0x00, SS_NEDEF|ENXIO, "Medium not present") }, ! /* DT WR OM */{SST(0x3A, 0x01, SS_NEDEF|ENXIO, "Medium not present - tray closed") }, ! /* DT WR OM */{SST(0x3A, 0x02, SS_NEDEF|ENXIO, "Medium not present - tray open") }, ! /* TL */{SST(0x3B, 0x00, SS_DEF, "Sequential positioning error") }, ! /* T */{SST(0x3B, 0x01, SS_DEF, "Tape position error at beginning-of-medium") }, ! /* T */{SST(0x3B, 0x02, SS_DEF, "Tape position error at end-of-medium") }, ! /* L */{SST(0x3B, 0x03, SS_DEF, "Tape or electronic vertical forms unit not ready") }, ! /* L */{SST(0x3B, 0x04, SS_DEF, "Slew failure") }, ! /* L */{SST(0x3B, 0x05, SS_DEF, "Paper jam") }, ! /* L */{SST(0x3B, 0x06, SS_DEF, "Failed to sense top-of-form") }, ! /* L */{SST(0x3B, 0x07, SS_DEF, "Failed to sense bottom-of-form") }, ! /* T */{SST(0x3B, 0x08, SS_DEF, "Reposition error") }, ! /* S */{SST(0x3B, 0x09, SS_DEF, "Read past end of medium") }, ! /* S */{SST(0x3B, 0x0A, SS_DEF, "Read past beginning of medium") }, ! /* S */{SST(0x3B, 0x0B, SS_DEF, "Position past end of medium") }, ! /* T S */{SST(0x3B, 0x0C, SS_DEF, "Position past beginning of medium") }, ! /* DT WR OM */{SST(0x3B, 0x0D, SS_NEDEF|ENOSPC, "Medium destination element full") }, ! /* DT WR OM */{SST(0x3B, 0x0E, SS_DEF, "Medium source element empty") }, ! /* R */{SST(0x3B, 0x0F, SS_DEF, "End of medium reached") }, ! /* DT WR OM */{SST(0x3B, 0x11, SS_DEF, "Medium magazine not accessible") }, ! /* DT WR OM */{SST(0x3B, 0x12, SS_DEF, "Medium magazine removed") }, ! /* DT WR OM */{SST(0x3B, 0x13, SS_DEF, "Medium magazine inserted") }, ! /* DT WR OM */{SST(0x3B, 0x14, SS_DEF, "Medium magazine locked") }, ! /* DT WR OM */{SST(0x3B, 0x15, SS_DEF, "Medium magazine unlocked") }, ! /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_DEF, "Invalid bits in identify message") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_DEF, "Logical unit has not self-configured yet") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_DEF, "Logical unit failure") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_DEF, "Timeout on logical unit") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_DEF, "Target operating conditions have changed") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_DEF, "Microcode has been changed") }, ! /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_DEF, "Changed operating definition") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_DEF, "Inquiry data has changed") }, ! /* DT WR OMCAE */{SST(0x3F, 0x04, SS_DEF, "Component device attached") }, ! /* DT WR OMCAE */{SST(0x3F, 0x05, SS_DEF, "Device identifier changed") }, ! /* DT WR OMCAE */{SST(0x3F, 0x06, SS_DEF, "Redundancy group created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x07, SS_DEF, "Redundancy group deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x08, SS_DEF, "Spare created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x09, SS_DEF, "Spare deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_DEF, "Volume set created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_DEF, "Volume set deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_DEF, "Volume set deassigned") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_DEF, "Volume set reassigned") }, ! /* D */{SST(0x40, 0x00, SS_DEF, "Ram failure") }, /* deprecated - use 40 NN instead */ ! /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_DEF, "Diagnostic failure: ASCQ = Component ID") }, ! /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_DEF|SSQ_RANGE, NULL) },/* Range 0x80->0xFF */ ! /* D */{SST(0x41, 0x00, SS_DEF, "Data path failure") }, /* deprecated - use 40 NN instead */ ! /* D */{SST(0x42, 0x00, SS_DEF, "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */ ! /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_DEF, "Message error") }, ! /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_DEF, "Internal target failure") }, ! /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_DEF, "Select or reselect failure") }, ! /* DTLPWRSOMC */{SST(0x46, 0x00, SS_DEF, "Unsuccessful soft reset") }, ! /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_DEF, "SCSI parity error") }, ! /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_DEF, "Initiator detected error message received") }, ! /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_DEF, "Invalid message error") }, ! /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_DEF, "Command phase error") }, ! /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_DEF, "Data phase error") }, ! /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_DEF, "Logical unit failed self-configuration") }, ! /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_DEF, "Tagged overlapped commands: ASCQ = Queue tag ID") }, ! /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_DEF|SSQ_RANGE, NULL)}, /* Range 0x00->0xFF */ ! /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_DEF, "Overlapped commands attempted") }, ! /* T */{SST(0x50, 0x00, SS_DEF, "Write append error") }, ! /* T */{SST(0x50, 0x01, SS_DEF, "Write append position error") }, ! /* T */{SST(0x50, 0x02, SS_DEF, "Position error related to timing") }, ! /* T O */{SST(0x51, 0x00, SS_DEF, "Erase failure") }, ! /* T */{SST(0x52, 0x00, SS_DEF, "Cartridge fault") }, ! /* DTL WRSOM */{SST(0x53, 0x00, SS_DEF, "Media load or eject failed") }, ! /* T */{SST(0x53, 0x01, SS_DEF, "Unload tape failure") }, ! /* DT WR OM */{SST(0x53, 0x02, SS_DEF, "Medium removal prevented") }, ! /* P */{SST(0x54, 0x00, SS_DEF, "Scsi to host system interface failure") }, ! /* P */{SST(0x55, 0x00, SS_DEF, "System resource failure") }, ! /* D O */{SST(0x55, 0x01, SS_NEDEF|ENOSPC, "System buffer full") }, ! /* R */{SST(0x57, 0x00, SS_DEF, "Unable to recover table-of-contents") }, ! /* O */{SST(0x58, 0x00, SS_DEF, "Generation does not exist") }, ! /* O */{SST(0x59, 0x00, SS_DEF, "Updated block read") }, ! /* DTLPWRSOM */{SST(0x5A, 0x00, SS_DEF, "Operator request or state change input") }, ! /* DT WR OM */{SST(0x5A, 0x01, SS_DEF, "Operator medium removal request") }, ! /* DT W O */{SST(0x5A, 0x02, SS_DEF, "Operator selected write protect") }, ! /* DT W O */{SST(0x5A, 0x03, SS_DEF, "Operator selected write permit") }, ! /* DTLPWRSOM */{SST(0x5B, 0x00, SS_DEF, "Log exception") }, ! /* DTLPWRSOM */{SST(0x5B, 0x01, SS_DEF, "Threshold condition met") }, ! /* DTLPWRSOM */{SST(0x5B, 0x02, SS_DEF, "Log counter at maximum") }, ! /* DTLPWRSOM */{SST(0x5B, 0x03, SS_DEF, "Log list codes exhausted") }, ! /* D O */{SST(0x5C, 0x00, SS_DEF, "RPL status change") }, ! /* D O */{SST(0x5C, 0x01, SS_NEDEF, "Spindles synchronized") }, ! /* D O */{SST(0x5C, 0x02, SS_DEF, "Spindles not synchronized") }, ! /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_DEF, "Failure prediction threshold exceeded") }, ! /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_DEF, "Failure prediction threshold exceeded (false)") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_DEF, "Low power condition on") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_DEF, "Idle condition activated by timer") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_DEF, "Standby condition activated by timer") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_DEF, "Idle condition activated by command") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_DEF, "Standby condition activated by command") }, ! /* S */{SST(0x60, 0x00, SS_DEF, "Lamp failure") }, ! /* S */{SST(0x61, 0x00, SS_DEF, "Video acquisition error") }, ! /* S */{SST(0x61, 0x01, SS_DEF, "Unable to acquire video") }, ! /* S */{SST(0x61, 0x02, SS_DEF, "Out of focus") }, ! /* S */{SST(0x62, 0x00, SS_DEF, "Scan head positioning error") }, ! /* R */{SST(0x63, 0x00, SS_DEF, "End of user area encountered on this track") }, ! /* R */{SST(0x63, 0x01, SS_NEDEF|ENOSPC, "Packet does not fit in available space") }, ! /* R */{SST(0x64, 0x00, SS_DEF, "Illegal mode for this track") }, ! /* R */{SST(0x64, 0x01, SS_DEF, "Invalid packet size") }, ! /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_DEF, "Voltage fault") }, ! /* S */{SST(0x66, 0x00, SS_DEF, "Automatic document feeder cover up") }, ! /* S */{SST(0x66, 0x01, SS_DEF, "Automatic document feeder lift up") }, ! /* S */{SST(0x66, 0x02, SS_DEF, "Document jam in automatic document feeder") }, ! /* S */{SST(0x66, 0x03, SS_DEF, "Document miss feed automatic in document feeder") }, ! /* A */{SST(0x67, 0x00, SS_DEF, "Configuration failure") }, ! /* A */{SST(0x67, 0x01, SS_DEF, "Configuration of incapable logical units failed") }, ! /* A */{SST(0x67, 0x02, SS_DEF, "Add logical unit failed") }, ! /* A */{SST(0x67, 0x03, SS_DEF, "Modification of logical unit failed") }, ! /* A */{SST(0x67, 0x04, SS_DEF, "Exchange of logical unit failed") }, ! /* A */{SST(0x67, 0x05, SS_DEF, "Remove of logical unit failed") }, ! /* A */{SST(0x67, 0x06, SS_DEF, "Attachment of logical unit failed") }, ! /* A */{SST(0x67, 0x07, SS_DEF, "Creation of logical unit failed") }, ! /* A */{SST(0x68, 0x00, SS_DEF, "Logical unit not configured") }, ! /* A */{SST(0x69, 0x00, SS_DEF, "Data loss on logical unit") }, ! /* A */{SST(0x69, 0x01, SS_DEF, "Multiple logical unit failures") }, ! /* A */{SST(0x69, 0x02, SS_DEF, "Parity/data mismatch") }, ! /* A */{SST(0x6A, 0x00, SS_DEF, "Informational, refer to log") }, ! /* A */{SST(0x6B, 0x00, SS_DEF, "State change has occurred") }, ! /* A */{SST(0x6B, 0x01, SS_DEF, "Redundancy level got better") }, ! /* A */{SST(0x6B, 0x02, SS_DEF, "Redundancy level got worse") }, ! /* A */{SST(0x6C, 0x00, SS_DEF, "Rebuild failure occurred") }, ! /* A */{SST(0x6D, 0x00, SS_DEF, "Recalculate failure occurred") }, ! /* A */{SST(0x6E, 0x00, SS_DEF, "Command to logical unit failed") }, ! /* T */{SST(0x70, 0x00, SS_DEF, "Decompression exception short: ASCQ = Algorithm ID") }, ! /* T */{SST(0x70, 0xFF, SS_DEF|SSQ_RANGE, NULL) }, /* Range 0x00 -> 0xFF */ ! /* T */{SST(0x71, 0x00, SS_DEF, "Decompression exception long: ASCQ = Algorithm ID") }, ! /* T */{SST(0x71, 0xFF, SS_DEF|SSQ_RANGE, NULL) }, /* Range 0x00 -> 0xFF */ ! /* R */{SST(0x72, 0x00, SS_DEF, "Session fixation error") }, ! /* R */{SST(0x72, 0x01, SS_DEF, "Session fixation error writing lead-in") }, ! /* R */{SST(0x72, 0x02, SS_DEF, "Session fixation error writing lead-out") }, ! /* R */{SST(0x72, 0x03, SS_DEF, "Session fixation error - incomplete track in session") }, ! /* R */{SST(0x72, 0x04, SS_DEF, "Empty or partially written reserved track") }, ! /* R */{SST(0x73, 0x00, SS_DEF, "CD control error") }, ! /* R */{SST(0x73, 0x01, SS_DEF, "Power calibration area almost full") }, ! /* R */{SST(0x73, 0x02, SS_NEDEF|ENOSPC, "Power calibration area is full") }, ! /* R */{SST(0x73, 0x03, SS_DEF, "Power calibration area error") }, ! /* R */{SST(0x73, 0x04, SS_DEF, "Program memory area update failure") }, ! /* R */{SST(0x73, 0x05, SS_DEF, "program memory area is full") } }; ! #if !defined(SCSI_NO_SENSE_STRINGS) ! const char * ! scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data) { - int i, j; caddr_t match; ! struct asc_table_entry *table[2]; ! int table_size[2]; ! int num_tables; ! if (inq_data == NULL) ! return(NULL); ! match = cam_quirkmatch((caddr_t)inq_data, ! (caddr_t)asc_quirk_table, ! sizeof(asc_quirk_table)/sizeof(*asc_quirk_table), ! sizeof(*asc_quirk_table), scsi_inquiry_match); ! if (match != NULL) { ! table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info; ! table_size[0] = ! ((struct scsi_sense_quirk_entry *)match)->num_ascs; ! table[1] = asc_text; ! table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]); ! num_tables = 2; } else { ! table[0] = asc_text; ! table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]); ! num_tables = 1; } ! for (j = 0; j < num_tables; j++) { ! for (i = 0; i < table_size[j]; i++) { ! if (table[j][i].asc == asc) { ! /* Check for ranges */ ! if ((table[j][i].action & SSQ_RANGE) != 0) { ! ! if (table[j][i].ascq >= ascq ! && table[j][i-1].ascq <= ascq) ! return table[j][i-1].desc; ! continue; ! } ! ! if (table[j][i].ascq == ascq) ! return table[j][i].desc; ! } } } ! if (asc >= 0x80 && asc <= 0xff) ! return "Vendor Specific ASC"; ! if (ascq >= 0x80 && ascq <= 0xff) ! return "Vendor Specific ASCQ"; ! return "Reserved ASC/ASCQ pair"; } ! #else /* SCSI_NO_SENSE_STRINGS */ ! const char * ! scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data) { ! return (""); } - #endif /* ! * Given a particular failed CCB and its device type information, return ! * the appropriate action from either the sense code quirk table or the ! * sense code table. */ scsi_sense_action ! scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data) { ! caddr_t match; ! struct asc_table_entry *table[2]; ! int table_size[2]; ! int num_tables; ! int i, j; ! /* ! * If we don't have inquiry data, we can't match against any quirk ! * entries. ! */ ! if (inq_data != NULL) { ! match = cam_quirkmatch((caddr_t)inq_data, ! (caddr_t)asc_quirk_table, ! sizeof(asc_quirk_table) / ! sizeof(*asc_quirk_table), ! sizeof(*asc_quirk_table), ! scsi_inquiry_match); ! } else ! match = NULL; ! if (match != NULL) { ! table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info; ! table_size[0] = ! ((struct scsi_sense_quirk_entry *)match)->num_ascs; ! table[1] = asc_text; ! table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]); ! num_tables = 2; } else { ! table[0] = asc_text; ! table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]); ! num_tables = 1; ! } ! for (j = 0; j < num_tables; j++) { ! for (i = 0; i < table_size[j]; i++) { ! if (table[j][i].asc == asc) { ! /* Check for ranges */ ! if ((table[j][i].action & SSQ_RANGE) != 0){ ! ! if (table[j][i].ascq >= ascq ! && table[j][i-1].ascq <= ascq) ! return table[j][i].action; ! ! continue; ! } ! ! /* ! * Check to see if we have a match. If the ! * current ascq in the table is greater ! * than our ascq, and there aren't any more ! * tables to search, just return the ! * default action. ! */ ! if (table[j][i].ascq == ascq) ! return(table[j][i].action); ! else if ((j == (num_tables - 1)) && ! (table[j][i].ascq > ascq)) ! return(SS_DEF); } } } ! /* ! * If we get to this point, it's most likely a vendor specific ! * ASC and we don't have a quirk entry for it. Oh well, we just ! * tell the error handling code to take the default action. ! */ ! return(SS_DEF); } char * --- 812,1675 ---- "Logical unit is in process of becoming ready") }, /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO, "Logical unit not ready, initializing cmd. required") }, ! /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_FATAL|ENXIO, "Logical unit not ready, manual intervention required")}, ! /* DTL O */{SST(0x04, 0x04, SS_FATAL|EBUSY, "Logical unit not ready, format in progress") }, ! /* DT W OMCA */{SST(0x04, 0x05, SS_FATAL|EBUSY, "Logical unit not ready, rebuild in progress") }, ! /* DT W OMCA */{SST(0x04, 0x06, SS_FATAL|EBUSY, "Logical unit not ready, recalculation in progress") }, ! /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_FATAL|EBUSY, "Logical unit not ready, operation in progress") }, ! /* R */{SST(0x04, 0x08, SS_FATAL|EBUSY, "Logical unit not ready, long write in progress") }, ! /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_RDEF, "Logical unit does not respond to selection") }, ! /* D WR OM */{SST(0x06, 0x00, SS_RDEF, "No reference position found") }, ! /* DTL WRSOM */{SST(0x07, 0x00, SS_RDEF, "Multiple peripheral devices selected") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_RDEF, "Logical unit communication failure") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_RDEF, "Logical unit communication time-out") }, ! /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_RDEF, "Logical unit communication parity error") }, ! /* DT R OM */{SST(0x08, 0x03, SS_RDEF, "Logical unit communication crc error (ultra-dma/32)")}, ! /* DT WR O */{SST(0x09, 0x00, SS_RDEF, "Track following error") }, ! /* WR O */{SST(0x09, 0x01, SS_RDEF, "Tracking servo failure") }, ! /* WR O */{SST(0x09, 0x02, SS_RDEF, "Focus servo failure") }, ! /* WR O */{SST(0x09, 0x03, SS_RDEF, "Spindle servo failure") }, ! /* DT WR O */{SST(0x09, 0x04, SS_RDEF, "Head select fault") }, ! /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_FATAL|ENOSPC, "Error log overflow") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_RDEF, "Warning") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_RDEF, "Specified temperature exceeded") }, ! /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_RDEF, "Enclosure degraded") }, ! /* T RS */{SST(0x0C, 0x00, SS_RDEF, "Write error") }, ! /* D W O */{SST(0x0C, 0x01, SS_NOP|SSQ_PRINT_SENSE, "Write error - recovered with auto reallocation") }, ! /* D W O */{SST(0x0C, 0x02, SS_RDEF, "Write error - auto reallocation failed") }, ! /* D W O */{SST(0x0C, 0x03, SS_RDEF, "Write error - recommend reassignment") }, ! /* DT W O */{SST(0x0C, 0x04, SS_RDEF, "Compression check miscompare error") }, ! /* DT W O */{SST(0x0C, 0x05, SS_RDEF, "Data expansion occurred during compression") }, ! /* DT W O */{SST(0x0C, 0x06, SS_RDEF, "Block not compressible") }, ! /* R */{SST(0x0C, 0x07, SS_RDEF, "Write error - recovery needed") }, ! /* R */{SST(0x0C, 0x08, SS_RDEF, "Write error - recovery failed") }, ! /* R */{SST(0x0C, 0x09, SS_RDEF, "Write error - loss of streaming") }, ! /* R */{SST(0x0C, 0x0A, SS_RDEF, "Write error - padding blocks added") }, ! /* D W O */{SST(0x10, 0x00, SS_RDEF, "ID CRC or ECC error") }, ! /* DT WRSO */{SST(0x11, 0x00, SS_RDEF, "Unrecovered read error") }, ! /* DT W SO */{SST(0x11, 0x01, SS_RDEF, "Read retries exhausted") }, ! /* DT W SO */{SST(0x11, 0x02, SS_RDEF, "Error too long to correct") }, ! /* DT W SO */{SST(0x11, 0x03, SS_RDEF, "Multiple read errors") }, ! /* D W O */{SST(0x11, 0x04, SS_RDEF, "Unrecovered read error - auto reallocate failed") }, ! /* WR O */{SST(0x11, 0x05, SS_RDEF, "L-EC uncorrectable error") }, ! /* WR O */{SST(0x11, 0x06, SS_RDEF, "CIRC unrecovered error") }, ! /* W O */{SST(0x11, 0x07, SS_RDEF, "Data re-synchronization error") }, ! /* T */{SST(0x11, 0x08, SS_RDEF, "Incomplete block read") }, ! /* T */{SST(0x11, 0x09, SS_RDEF, "No gap found") }, ! /* DT O */{SST(0x11, 0x0A, SS_RDEF, "Miscorrected error") }, ! /* D W O */{SST(0x11, 0x0B, SS_RDEF, "Unrecovered read error - recommend reassignment") }, ! /* D W O */{SST(0x11, 0x0C, SS_RDEF, "Unrecovered read error - recommend rewrite the data")}, ! /* DT WR O */{SST(0x11, 0x0D, SS_RDEF, "De-compression CRC error") }, ! /* DT WR O */{SST(0x11, 0x0E, SS_RDEF, "Cannot decompress using declared algorithm") }, ! /* R */{SST(0x11, 0x0F, SS_RDEF, "Error reading UPC/EAN number") }, ! /* R */{SST(0x11, 0x10, SS_RDEF, "Error reading ISRC number") }, ! /* R */{SST(0x11, 0x11, SS_RDEF, "Read error - loss of streaming") }, ! /* D W O */{SST(0x12, 0x00, SS_RDEF, "Address mark not found for id field") }, ! /* D W O */{SST(0x13, 0x00, SS_RDEF, "Address mark not found for data field") }, ! /* DTL WRSO */{SST(0x14, 0x00, SS_RDEF, "Recorded entity not found") }, ! /* DT WR O */{SST(0x14, 0x01, SS_RDEF, "Record not found") }, ! /* T */{SST(0x14, 0x02, SS_RDEF, "Filemark or setmark not found") }, ! /* T */{SST(0x14, 0x03, SS_RDEF, "End-of-data not found") }, ! /* T */{SST(0x14, 0x04, SS_RDEF, "Block sequence error") }, ! /* DT W O */{SST(0x14, 0x05, SS_RDEF, "Record not found - recommend reassignment") }, ! /* DT W O */{SST(0x14, 0x06, SS_RDEF, "Record not found - data auto-reallocated") }, ! /* DTL WRSOM */{SST(0x15, 0x00, SS_RDEF, "Random positioning error") }, ! /* DTL WRSOM */{SST(0x15, 0x01, SS_RDEF, "Mechanical positioning error") }, ! /* DT WR O */{SST(0x15, 0x02, SS_RDEF, "Positioning error detected by read of medium") }, ! /* D W O */{SST(0x16, 0x00, SS_RDEF, "Data synchronization mark error") }, ! /* D W O */{SST(0x16, 0x01, SS_RDEF, "Data sync error - data rewritten") }, ! /* D W O */{SST(0x16, 0x02, SS_RDEF, "Data sync error - recommend rewrite") }, ! /* D W O */{SST(0x16, 0x03, SS_NOP|SSQ_PRINT_SENSE, "Data sync error - data auto-reallocated") }, ! /* D W O */{SST(0x16, 0x04, SS_RDEF, "Data sync error - recommend reassignment") }, ! /* DT WRSO */{SST(0x17, 0x00, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with no error correction applied") }, ! /* DT WRSO */{SST(0x17, 0x01, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with retries") }, ! /* DT WR O */{SST(0x17, 0x02, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with positive head offset") }, ! /* DT WR O */{SST(0x17, 0x03, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with negative head offset") }, ! /* WR O */{SST(0x17, 0x04, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with retries and/or CIRC applied") }, ! /* D WR O */{SST(0x17, 0x05, SS_NOP|SSQ_PRINT_SENSE, "Recovered data using previous sector id") }, ! /* D W O */{SST(0x17, 0x06, SS_NOP|SSQ_PRINT_SENSE, "Recovered data without ECC - data auto-reallocated") }, ! /* D W O */{SST(0x17, 0x07, SS_NOP|SSQ_PRINT_SENSE, "Recovered data without ECC - recommend reassignment")}, ! /* D W O */{SST(0x17, 0x08, SS_NOP|SSQ_PRINT_SENSE, "Recovered data without ECC - recommend rewrite") }, ! /* D W O */{SST(0x17, 0x09, SS_NOP|SSQ_PRINT_SENSE, "Recovered data without ECC - data rewritten") }, ! /* D W O */{SST(0x18, 0x00, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with error correction applied") }, ! /* D WR O */{SST(0x18, 0x01, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with error corr. & retries applied") }, ! /* D WR O */{SST(0x18, 0x02, SS_NOP|SSQ_PRINT_SENSE, "Recovered data - data auto-reallocated") }, ! /* R */{SST(0x18, 0x03, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with CIRC") }, ! /* R */{SST(0x18, 0x04, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with L-EC") }, ! /* D WR O */{SST(0x18, 0x05, SS_NOP|SSQ_PRINT_SENSE, "Recovered data - recommend reassignment") }, ! /* D WR O */{SST(0x18, 0x06, SS_NOP|SSQ_PRINT_SENSE, "Recovered data - recommend rewrite") }, ! /* D W O */{SST(0x18, 0x07, SS_NOP|SSQ_PRINT_SENSE, "Recovered data with ECC - data rewritten") }, ! /* D O */{SST(0x19, 0x00, SS_RDEF, "Defect list error") }, ! /* D O */{SST(0x19, 0x01, SS_RDEF, "Defect list not available") }, ! /* D O */{SST(0x19, 0x02, SS_RDEF, "Defect list error in primary list") }, ! /* D O */{SST(0x19, 0x03, SS_RDEF, "Defect list error in grown list") }, ! /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_RDEF, "Parameter list length error") }, ! /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_RDEF, "Synchronous data transfer error") }, ! /* D O */{SST(0x1C, 0x00, SS_RDEF, "Defect list not found") }, ! /* D O */{SST(0x1C, 0x01, SS_RDEF, "Primary defect list not found") }, ! /* D O */{SST(0x1C, 0x02, SS_RDEF, "Grown defect list not found") }, ! /* D W O */{SST(0x1D, 0x00, SS_FATAL, "Miscompare during verify operation" )}, ! /* D W O */{SST(0x1E, 0x00, SS_NOP|SSQ_PRINT_SENSE, "Recovered id with ecc correction") }, ! /* D O */{SST(0x1F, 0x00, SS_RDEF, "Partial defect list transfer") }, ! /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_FATAL|EINVAL, "Invalid command operation code") }, ! /* DT WR OM */{SST(0x21, 0x00, SS_FATAL|EINVAL, "Logical block address out of range" )}, ! /* DT WR OM */{SST(0x21, 0x01, SS_FATAL|EINVAL, "Invalid element address") }, ! /* D */{SST(0x22, 0x00, SS_FATAL|EINVAL, "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */ ! /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_FATAL|EINVAL, "Invalid field in CDB") }, ! /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_FATAL|ENXIO, "Logical unit not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_FATAL|EINVAL, "Invalid field in parameter list") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_FATAL|EINVAL, "Parameter not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_FATAL|EINVAL, "Parameter value invalid") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_FATAL|EINVAL, "Threshold parameters not supported") }, ! /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_FATAL|EINVAL, "Invalid release of active persistent reservation") }, ! /* DT W O */{SST(0x27, 0x00, SS_FATAL|EACCES, "Write protected") }, ! /* DT W O */{SST(0x27, 0x01, SS_FATAL|EACCES, "Hardware write protected") }, ! /* DT W O */{SST(0x27, 0x02, SS_FATAL|EACCES, "Logical unit software write protected") }, ! /* T */{SST(0x27, 0x03, SS_FATAL|EACCES, "Associated write protect") }, ! /* T */{SST(0x27, 0x04, SS_FATAL|EACCES, "Persistent write protect") }, ! /* T */{SST(0x27, 0x05, SS_FATAL|EACCES, "Permanent write protect") }, ! /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_FATAL|ENXIO, "Not ready to ready change, medium may have changed") }, ! /* DTLPWRSOMCAE */{SST(0x28, 0x01, SS_FATAL|ENXIO, "Import or export element accessed") }, ! /* ! * XXX JGibbs - All of these should use the same errno, but I don't think ! * ENXIO is the correct choice. Should we borrow from the networking ! * errnos? ECONNRESET anyone? ! */ ! /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_FATAL|ENXIO, "Power on, reset, or bus device reset occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_RDEF, "Power on occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_RDEF, "Scsi bus reset occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_RDEF, "Bus device reset function occurred") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_RDEF, "Device internal reset") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_RDEF, "Transceiver mode changed to single-ended") }, ! /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_RDEF, "Transceiver mode changed to LVD") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_RDEF, "Parameters changed") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_RDEF, "Mode parameters changed") }, ! /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_RDEF, "Log parameters changed") }, ! /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_RDEF, "Reservations preempted") }, ! /* DTLPWRSO C */{SST(0x2B, 0x00, SS_RDEF, "Copy cannot execute since host cannot disconnect") }, ! /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_RDEF, "Command sequence error") }, ! /* S */{SST(0x2C, 0x01, SS_RDEF, "Too many windows specified") }, ! /* S */{SST(0x2C, 0x02, SS_RDEF, "Invalid combination of windows specified") }, ! /* R */{SST(0x2C, 0x03, SS_RDEF, "Current program area is not empty") }, ! /* R */{SST(0x2C, 0x04, SS_RDEF, "Current program area is empty") }, ! /* T */{SST(0x2D, 0x00, SS_RDEF, "Overwrite error on update in place") }, ! /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_RDEF, "Commands cleared by another initiator") }, ! /* DT WR OM */{SST(0x30, 0x00, SS_RDEF, "Incompatible medium installed") }, ! /* DT WR O */{SST(0x30, 0x01, SS_RDEF, "Cannot read medium - unknown format") }, ! /* DT WR O */{SST(0x30, 0x02, SS_RDEF, "Cannot read medium - incompatible format") }, ! /* DT */{SST(0x30, 0x03, SS_RDEF, "Cleaning cartridge installed") }, ! /* DT WR O */{SST(0x30, 0x04, SS_RDEF, "Cannot write medium - unknown format") }, ! /* DT WR O */{SST(0x30, 0x05, SS_RDEF, "Cannot write medium - incompatible format") }, ! /* DT W O */{SST(0x30, 0x06, SS_RDEF, "Cannot format medium - incompatible medium") }, ! /* DTL WRSOM AE */{SST(0x30, 0x07, SS_RDEF, "Cleaning failure") }, ! /* R */{SST(0x30, 0x08, SS_RDEF, "Cannot write - application code mismatch") }, ! /* R */{SST(0x30, 0x09, SS_RDEF, "Current session not fixated for append") }, ! /* DT WR O */{SST(0x31, 0x00, SS_RDEF, "Medium format corrupted") }, ! /* D L R O */{SST(0x31, 0x01, SS_RDEF, "Format command failed") }, ! /* D W O */{SST(0x32, 0x00, SS_RDEF, "No defect spare location available") }, ! /* D W O */{SST(0x32, 0x01, SS_RDEF, "Defect list update failure") }, ! /* T */{SST(0x33, 0x00, SS_RDEF, "Tape length error") }, ! /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_RDEF, "Enclosure failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_RDEF, "Enclosure services failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_RDEF, "Unsupported enclosure function") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_RDEF, "Enclosure services unavailable") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_RDEF, "Enclosure services transfer failure") }, ! /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_RDEF, "Enclosure services transfer refused") }, ! /* L */{SST(0x36, 0x00, SS_RDEF, "Ribbon, ink, or toner failure") }, ! /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_RDEF, "Rounded parameter") }, ! /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_RDEF, "Saving parameters not supported") }, ! /* DTL WRSOM */{SST(0x3A, 0x00, SS_FATAL|ENXIO, "Medium not present") }, ! /* DT WR OM */{SST(0x3A, 0x01, SS_FATAL|ENXIO, "Medium not present - tray closed") }, ! /* DT WR OM */{SST(0x3A, 0x02, SS_FATAL|ENXIO, "Medium not present - tray open") }, ! /* TL */{SST(0x3B, 0x00, SS_RDEF, "Sequential positioning error") }, ! /* T */{SST(0x3B, 0x01, SS_RDEF, "Tape position error at beginning-of-medium") }, ! /* T */{SST(0x3B, 0x02, SS_RDEF, "Tape position error at end-of-medium") }, ! /* L */{SST(0x3B, 0x03, SS_RDEF, "Tape or electronic vertical forms unit not ready") }, ! /* L */{SST(0x3B, 0x04, SS_RDEF, "Slew failure") }, ! /* L */{SST(0x3B, 0x05, SS_RDEF, "Paper jam") }, ! /* L */{SST(0x3B, 0x06, SS_RDEF, "Failed to sense top-of-form") }, ! /* L */{SST(0x3B, 0x07, SS_RDEF, "Failed to sense bottom-of-form") }, ! /* T */{SST(0x3B, 0x08, SS_RDEF, "Reposition error") }, ! /* S */{SST(0x3B, 0x09, SS_RDEF, "Read past end of medium") }, ! /* S */{SST(0x3B, 0x0A, SS_RDEF, "Read past beginning of medium") }, ! /* S */{SST(0x3B, 0x0B, SS_RDEF, "Position past end of medium") }, ! /* T S */{SST(0x3B, 0x0C, SS_RDEF, "Position past beginning of medium") }, ! /* DT WR OM */{SST(0x3B, 0x0D, SS_FATAL|ENOSPC, "Medium destination element full") }, ! /* DT WR OM */{SST(0x3B, 0x0E, SS_RDEF, "Medium source element empty") }, ! /* R */{SST(0x3B, 0x0F, SS_RDEF, "End of medium reached") }, ! /* DT WR OM */{SST(0x3B, 0x11, SS_RDEF, "Medium magazine not accessible") }, ! /* DT WR OM */{SST(0x3B, 0x12, SS_RDEF, "Medium magazine removed") }, ! /* DT WR OM */{SST(0x3B, 0x13, SS_RDEF, "Medium magazine inserted") }, ! /* DT WR OM */{SST(0x3B, 0x14, SS_RDEF, "Medium magazine locked") }, ! /* DT WR OM */{SST(0x3B, 0x15, SS_RDEF, "Medium magazine unlocked") }, ! /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_RDEF, "Invalid bits in identify message") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_RDEF, "Logical unit has not self-configured yet") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_RDEF, "Logical unit failure") }, ! /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_RDEF, "Timeout on logical unit") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_RDEF, "Target operating conditions have changed") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_RDEF, "Microcode has been changed") }, ! /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_RDEF, "Changed operating definition") }, ! /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_RDEF, "Inquiry data has changed") }, ! /* DT WR OMCAE */{SST(0x3F, 0x04, SS_RDEF, "Component device attached") }, ! /* DT WR OMCAE */{SST(0x3F, 0x05, SS_RDEF, "Device identifier changed") }, ! /* DT WR OMCAE */{SST(0x3F, 0x06, SS_RDEF, "Redundancy group created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x07, SS_RDEF, "Redundancy group deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x08, SS_RDEF, "Spare created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x09, SS_RDEF, "Spare deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_RDEF, "Volume set created or modified") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_RDEF, "Volume set deleted") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_RDEF, "Volume set deassigned") }, ! /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_RDEF, "Volume set reassigned") }, ! /* D */{SST(0x40, 0x00, SS_RDEF, "Ram failure") }, /* deprecated - use 40 NN instead */ ! /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_RDEF, "Diagnostic failure: ASCQ = Component ID") }, ! /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_RDEF|SSQ_RANGE, NULL) },/* Range 0x80->0xFF */ ! /* D */{SST(0x41, 0x00, SS_RDEF, "Data path failure") }, /* deprecated - use 40 NN instead */ ! /* D */{SST(0x42, 0x00, SS_RDEF, "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */ ! /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_RDEF, "Message error") }, ! /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_RDEF, "Internal target failure") }, ! /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_RDEF, "Select or reselect failure") }, ! /* DTLPWRSOMC */{SST(0x46, 0x00, SS_RDEF, "Unsuccessful soft reset") }, ! /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_RDEF, "SCSI parity error") }, ! /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_RDEF, "Initiator detected error message received") }, ! /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_RDEF, "Invalid message error") }, ! /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_RDEF, "Command phase error") }, ! /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_RDEF, "Data phase error") }, ! /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_RDEF, "Logical unit failed self-configuration") }, ! /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_RDEF, "Tagged overlapped commands: ASCQ = Queue tag ID") }, ! /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_RDEF|SSQ_RANGE, NULL)}, /* Range 0x00->0xFF */ ! /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_RDEF, "Overlapped commands attempted") }, ! /* T */{SST(0x50, 0x00, SS_RDEF, "Write append error") }, ! /* T */{SST(0x50, 0x01, SS_RDEF, "Write append position error") }, ! /* T */{SST(0x50, 0x02, SS_RDEF, "Position error related to timing") }, ! /* T O */{SST(0x51, 0x00, SS_RDEF, "Erase failure") }, ! /* T */{SST(0x52, 0x00, SS_RDEF, "Cartridge fault") }, ! /* DTL WRSOM */{SST(0x53, 0x00, SS_RDEF, "Media load or eject failed") }, ! /* T */{SST(0x53, 0x01, SS_RDEF, "Unload tape failure") }, ! /* DT WR OM */{SST(0x53, 0x02, SS_RDEF, "Medium removal prevented") }, ! /* P */{SST(0x54, 0x00, SS_RDEF, "Scsi to host system interface failure") }, ! /* P */{SST(0x55, 0x00, SS_RDEF, "System resource failure") }, ! /* D O */{SST(0x55, 0x01, SS_FATAL|ENOSPC, "System buffer full") }, ! /* R */{SST(0x57, 0x00, SS_RDEF, "Unable to recover table-of-contents") }, ! /* O */{SST(0x58, 0x00, SS_RDEF, "Generation does not exist") }, ! /* O */{SST(0x59, 0x00, SS_RDEF, "Updated block read") }, ! /* DTLPWRSOM */{SST(0x5A, 0x00, SS_RDEF, "Operator request or state change input") }, ! /* DT WR OM */{SST(0x5A, 0x01, SS_RDEF, "Operator medium removal request") }, ! /* DT W O */{SST(0x5A, 0x02, SS_RDEF, "Operator selected write protect") }, ! /* DT W O */{SST(0x5A, 0x03, SS_RDEF, "Operator selected write permit") }, ! /* DTLPWRSOM */{SST(0x5B, 0x00, SS_RDEF, "Log exception") }, ! /* DTLPWRSOM */{SST(0x5B, 0x01, SS_RDEF, "Threshold condition met") }, ! /* DTLPWRSOM */{SST(0x5B, 0x02, SS_RDEF, "Log counter at maximum") }, ! /* DTLPWRSOM */{SST(0x5B, 0x03, SS_RDEF, "Log list codes exhausted") }, ! /* D O */{SST(0x5C, 0x00, SS_RDEF, "RPL status change") }, ! /* D O */{SST(0x5C, 0x01, SS_NOP|SSQ_PRINT_SENSE, "Spindles synchronized") }, ! /* D O */{SST(0x5C, 0x02, SS_RDEF, "Spindles not synchronized") }, ! /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_RDEF, "Failure prediction threshold exceeded") }, ! /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_RDEF, "Failure prediction threshold exceeded (false)") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_RDEF, "Low power condition on") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_RDEF, "Idle condition activated by timer") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_RDEF, "Standby condition activated by timer") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_RDEF, "Idle condition activated by command") }, ! /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_RDEF, "Standby condition activated by command") }, ! /* S */{SST(0x60, 0x00, SS_RDEF, "Lamp failure") }, ! /* S */{SST(0x61, 0x00, SS_RDEF, "Video acquisition error") }, ! /* S */{SST(0x61, 0x01, SS_RDEF, "Unable to acquire video") }, ! /* S */{SST(0x61, 0x02, SS_RDEF, "Out of focus") }, ! /* S */{SST(0x62, 0x00, SS_RDEF, "Scan head positioning error") }, ! /* R */{SST(0x63, 0x00, SS_RDEF, "End of user area encountered on this track") }, ! /* R */{SST(0x63, 0x01, SS_FATAL|ENOSPC, "Packet does not fit in available space") }, ! /* R */{SST(0x64, 0x00, SS_RDEF, "Illegal mode for this track") }, ! /* R */{SST(0x64, 0x01, SS_RDEF, "Invalid packet size") }, ! /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_RDEF, "Voltage fault") }, ! /* S */{SST(0x66, 0x00, SS_RDEF, "Automatic document feeder cover up") }, ! /* S */{SST(0x66, 0x01, SS_RDEF, "Automatic document feeder lift up") }, ! /* S */{SST(0x66, 0x02, SS_RDEF, "Document jam in automatic document feeder") }, ! /* S */{SST(0x66, 0x03, SS_RDEF, "Document miss feed automatic in document feeder") }, ! /* A */{SST(0x67, 0x00, SS_RDEF, "Configuration failure") }, ! /* A */{SST(0x67, 0x01, SS_RDEF, "Configuration of incapable logical units failed") }, ! /* A */{SST(0x67, 0x02, SS_RDEF, "Add logical unit failed") }, ! /* A */{SST(0x67, 0x03, SS_RDEF, "Modification of logical unit failed") }, ! /* A */{SST(0x67, 0x04, SS_RDEF, "Exchange of logical unit failed") }, ! /* A */{SST(0x67, 0x05, SS_RDEF, "Remove of logical unit failed") }, ! /* A */{SST(0x67, 0x06, SS_RDEF, "Attachment of logical unit failed") }, ! /* A */{SST(0x67, 0x07, SS_RDEF, "Creation of logical unit failed") }, ! /* A */{SST(0x68, 0x00, SS_RDEF, "Logical unit not configured") }, ! /* A */{SST(0x69, 0x00, SS_RDEF, "Data loss on logical unit") }, ! /* A */{SST(0x69, 0x01, SS_RDEF, "Multiple logical unit failures") }, ! /* A */{SST(0x69, 0x02, SS_RDEF, "Parity/data mismatch") }, ! /* A */{SST(0x6A, 0x00, SS_RDEF, "Informational, refer to log") }, ! /* A */{SST(0x6B, 0x00, SS_RDEF, "State change has occurred") }, ! /* A */{SST(0x6B, 0x01, SS_RDEF, "Redundancy level got better") }, ! /* A */{SST(0x6B, 0x02, SS_RDEF, "Redundancy level got worse") }, ! /* A */{SST(0x6C, 0x00, SS_RDEF, "Rebuild failure occurred") }, ! /* A */{SST(0x6D, 0x00, SS_RDEF, "Recalculate failure occurred") }, ! /* A */{SST(0x6E, 0x00, SS_RDEF, "Command to logical unit failed") }, ! /* T */{SST(0x70, 0x00, SS_RDEF, "Decompression exception short: ASCQ = Algorithm ID") }, ! /* T */{SST(0x70, 0xFF, SS_RDEF|SSQ_RANGE, NULL) }, /* Range 0x00 -> 0xFF */ ! /* T */{SST(0x71, 0x00, SS_RDEF, "Decompression exception long: ASCQ = Algorithm ID") }, ! /* T */{SST(0x71, 0xFF, SS_RDEF|SSQ_RANGE, NULL) }, /* Range 0x00 -> 0xFF */ ! /* R */{SST(0x72, 0x00, SS_RDEF, "Session fixation error") }, ! /* R */{SST(0x72, 0x01, SS_RDEF, "Session fixation error writing lead-in") }, ! /* R */{SST(0x72, 0x02, SS_RDEF, "Session fixation error writing lead-out") }, ! /* R */{SST(0x72, 0x03, SS_RDEF, "Session fixation error - incomplete track in session") }, ! /* R */{SST(0x72, 0x04, SS_RDEF, "Empty or partially written reserved track") }, ! /* R */{SST(0x73, 0x00, SS_RDEF, "CD control error") }, ! /* R */{SST(0x73, 0x01, SS_RDEF, "Power calibration area almost full") }, ! /* R */{SST(0x73, 0x02, SS_FATAL|ENOSPC, "Power calibration area is full") }, ! /* R */{SST(0x73, 0x03, SS_RDEF, "Power calibration area error") }, ! /* R */{SST(0x73, 0x04, SS_RDEF, "Program memory area update failure") }, ! /* R */{SST(0x73, 0x05, SS_RDEF, "program memory area is full") } }; ! const int asc_table_size = sizeof(asc_table)/sizeof(asc_table[0]); ! ! struct asc_key ! { ! int asc; ! int ascq; ! }; ! ! static int ! ascentrycomp(const void *key, const void *member) ! { ! int asc; ! int ascq; ! const struct asc_table_entry *table_entry; ! ! asc = ((const struct asc_key *)key)->asc; ! ascq = ((const struct asc_key *)key)->ascq; ! table_entry = (const struct asc_table_entry *)member; ! ! if (asc >= table_entry->asc) { ! ! if (asc > table_entry->asc) ! return (1); ! ! if (ascq <= table_entry->ascq) { ! /* Check for ranges */ ! if (ascq == table_entry->ascq ! || ((table_entry->action & SSQ_RANGE) != 0 ! && ascq >= (table_entry - 1)->ascq)) ! return (0); ! return (-1); ! } ! return (1); ! } ! return (-1); ! } ! ! static int ! senseentrycomp(const void *key, const void *member) ! { ! int sense_key; ! const struct sense_key_table_entry *table_entry; ! ! sense_key = *((const int *)key); ! table_entry = (const struct sense_key_table_entry *)member; ! ! if (sense_key >= table_entry->sense_key) { ! if (sense_key == table_entry->sense_key) ! return (0); ! return (1); ! } ! return (-1); ! } ! ! static void ! fetchtableentries(int sense_key, int asc, int ascq, ! struct scsi_inquiry_data *inq_data, ! const struct sense_key_table_entry **sense_entry, ! const struct asc_table_entry **asc_entry) { caddr_t match; ! const struct asc_table_entry *asc_tables[2]; ! const struct sense_key_table_entry *sense_tables[2]; ! struct asc_key asc_ascq; ! size_t asc_tables_size[2]; ! size_t sense_tables_size[2]; ! int num_asc_tables; ! int num_sense_tables; ! int i; ! /* Default to failure */ ! *sense_entry = NULL; ! *asc_entry = NULL; ! match = NULL; ! if (inq_data != NULL) ! match = cam_quirkmatch((caddr_t)inq_data, ! (caddr_t)sense_quirk_table, ! sense_quirk_table_size, ! sizeof(*sense_quirk_table), ! scsi_inquiry_match); ! if (match != NULL) { ! struct scsi_sense_quirk_entry *quirk; ! quirk = (struct scsi_sense_quirk_entry *)match; ! asc_tables[0] = quirk->asc_info; ! asc_tables_size[0] = quirk->num_ascs; ! asc_tables[1] = asc_table; ! asc_tables_size[1] = asc_table_size; ! num_asc_tables = 2; ! sense_tables[0] = quirk->sense_key_info; ! sense_tables_size[0] = quirk->num_sense_keys; ! sense_tables[1] = sense_key_table; ! sense_tables_size[1] = sense_key_table_size; ! num_sense_tables = 2; } else { ! asc_tables[0] = asc_table; ! asc_tables_size[0] = asc_table_size; ! num_asc_tables = 1; ! sense_tables[0] = sense_key_table; ! sense_tables_size[0] = sense_key_table_size; ! num_sense_tables = 1; } ! asc_ascq.asc = asc; ! asc_ascq.ascq = ascq; ! for (i = 0; i < num_asc_tables; i++) { ! void *found_entry; ! found_entry = bsearch(&asc_ascq, asc_tables[i], ! asc_tables_size[i], ! sizeof(**asc_tables), ! ascentrycomp); ! if (found_entry) { ! *asc_entry = (struct asc_table_entry *)found_entry; ! break; } } ! for (i = 0; i < num_sense_tables; i++) { ! void *found_entry; ! found_entry = bsearch(&sense_key, sense_tables[i], ! sense_tables_size[i], ! sizeof(**sense_tables), ! senseentrycomp); ! if (found_entry) { ! *sense_entry = ! (struct sense_key_table_entry *)found_entry; ! break; ! } ! } } ! 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) { ! const struct asc_table_entry *asc_entry; ! const struct sense_key_table_entry *sense_entry; ! ! fetchtableentries(sense_key, asc, ascq, ! inq_data, ! &sense_entry, ! &asc_entry); ! ! *sense_key_desc = sense_entry->desc; ! ! if (asc_entry != NULL) ! *asc_desc = asc_entry->desc; ! else if (asc >= 0x80 && asc <= 0xff) ! *asc_desc = "Vendor Specific ASC"; ! else if (ascq >= 0x80 && ascq <= 0xff) ! *asc_desc = "Vendor Specific ASCQ"; ! else ! *asc_desc = "Reserved ASC/ASCQ pair"; } /* ! * Given sense and device type information, return the appropriate action. ! * If we do not understand the specific error as identified by the ASC/ASCQ ! * pair, fall back on the more generic actions derived from the sense key. */ scsi_sense_action ! scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data, ! u_int32_t sense_flags) { ! const struct asc_table_entry *asc_entry; ! const struct sense_key_table_entry *sense_entry; ! int error_code, sense_key, asc, ascq; ! scsi_sense_action action; ! scsi_extract_sense(&csio->sense_data, &error_code, ! &sense_key, &asc, &ascq); ! if (error_code == SSD_DEFERRED_ERROR) { ! /* ! * XXX dufault@FreeBSD.org ! * This error doesn't relate to the command associated ! * with this request sense. A deferred error is an error ! * for a command that has already returned GOOD status ! * (see SCSI2 8.2.14.2). ! * ! * By my reading of that section, it looks like the current ! * command has been cancelled, we should now clean things up ! * (hopefully recovering any lost data) and then retry the ! * current command. There are two easy choices, both wrong: ! * ! * 1. Drop through (like we had been doing), thus treating ! * this as if the error were for the current command and ! * return and stop the current command. ! * ! * 2. Issue a retry (like I made it do) thus hopefully ! * recovering the current transfer, and ignoring the ! * fact that we've dropped a command. ! * ! * These should probably be handled in a device specific ! * sense handler or punted back up to a user mode daemon ! */ ! action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE; } else { ! fetchtableentries(sense_key, asc, ascq, ! inq_data, ! &sense_entry, ! &asc_entry); ! /* ! * Override the 'No additional Sense' entry (0,0) ! * with the error action of the sense key. ! */ ! if (asc_entry != NULL ! && (asc != 0 || ascq != 0)) ! action = asc_entry->action; ! else ! action = sense_entry->action; ! if (sense_key == SSD_KEY_RECOVERED_ERROR) { ! /* ! * The action succeeded but the device wants ! * the user to know that some recovery action ! * was required. ! */ ! action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK); ! action |= SS_NOP|SSQ_PRINT_SENSE; ! } else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) { ! if ((sense_flags & SF_QUIET_IR) != 0) ! action &= ~SSQ_PRINT_SENSE; ! } else if (sense_key == SSD_KEY_UNIT_ATTENTION) { ! if ((sense_flags & SF_RETRY_UA) != 0 ! && (action & SS_MASK) == SS_FAIL) { ! action &= ~(SS_MASK|SSQ_MASK); ! action |= SS_RETRY|SSQ_DECREMENT_COUNT| ! SSQ_PRINT_SENSE; } } } ! #ifdef KERNEL ! if (bootverbose) ! sense_flags |= SF_PRINT_ALWAYS; ! #endif ! if ((sense_flags & SF_PRINT_ALWAYS) != 0) ! action |= SSQ_PRINT_SENSE; ! else if ((sense_flags & SF_NO_PRINT) != 0) ! action &= ~SSQ_PRINT_SENSE; ! ! return (action); } char * *************** *** 1600,1641 **** *cdb_string = '\0'; for (i = 0; i < cdb_len; i++) snprintf(cdb_string + strlen(cdb_string), ! len - strlen(cdb_string), "%x ", cdb_ptr[i]); return(cdb_string); } /* ! * scsi_sense_print will decode the sense data into human ! * readable form. Sense handlers can use this to generate ! * a report. */ - /* - * Because scsi_sense_print() utilizes transport layer functions, it will - * only work in the kernel. - */ #ifdef _KERNEL ! ! void ! scsi_sense_print(struct ccb_scsiio *csio) { ! struct scsi_sense_data *sense; ! u_int32_t info; ! int error_code; ! int sense_key; ! int asc, ascq; ! struct ccb_getdev cgd; ! u_int8_t command_print; ! sense = &csio->sense_data; ! ! /* ! * If the CDB is a physical address, we can't deal with it.. ! */ ! if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) ! command_print = 0; ! else ! command_print = 1; ! /* * Get the device information. */ --- 1722,1784 ---- *cdb_string = '\0'; for (i = 0; i < cdb_len; i++) snprintf(cdb_string + strlen(cdb_string), ! len - strlen(cdb_string), "%x ", cdb_ptr[i]); return(cdb_string); } + + const char * + scsi_status_string(struct ccb_scsiio *csio) + { + switch(csio->scsi_status) { + case SCSI_STATUS_OK: + return("OK"); + case SCSI_STATUS_CHECK_COND: + return("Check Condition"); + case SCSI_STATUS_BUSY: + return("Busy"); + case SCSI_STATUS_INTERMED: + return("Intermediate"); + case SCSI_STATUS_INTERMED_COND_MET: + return("Intermediate-Condition Met"); + case SCSI_STATUS_RESERV_CONFLICT: + return("Reservation Conflict"); + case SCSI_STATUS_CMD_TERMINATED: + return("Command Terminated"); + case SCSI_STATUS_QUEUE_FULL: + return("Queue Full"); + case SCSI_STATUS_ACA_ACTIVE: + return("ACA Active"); + case SCSI_STATUS_TASK_ABORTED: + return("Task Aborted"); + default: { + static char unkstr[64]; + snprintf(unkstr, sizeof(unkstr), "Unknown %#x", + csio->scsi_status); + return(unkstr); + } + } + } + /* ! * scsi_command_string() returns 0 for success and -1 for failure. */ #ifdef _KERNEL ! int ! scsi_command_string(struct ccb_scsiio *csio, struct sbuf *sb) ! #else /* !_KERNEL */ ! int ! scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio, ! struct sbuf *sb) ! #endif /* _KERNEL/!_KERNEL */ { ! struct scsi_inquiry_data *inq_data; ! char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; ! #ifdef _KERNEL ! struct ccb_getdev cgd; ! #endif /* _KERNEL */ ! #ifdef _KERNEL /* * Get the device information. */ *************** *** 1652,1860 **** if (cgd.ccb_h.status == CAM_DEV_NOT_THERE) cgd.inq_data.device = T_DIRECT; ! if (command_print != 0) { ! char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; ! xpt_print_path(csio->ccb_h.path); ! if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { ! printf("%s. CDB: %s\n", ! scsi_op_desc(csio->cdb_io.cdb_ptr[0], ! &cgd.inq_data), ! scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str, ! sizeof(cdb_str))); ! } else { ! printf("%s. CDB: %s\n", ! scsi_op_desc(csio->cdb_io.cdb_bytes[0], ! &cgd.inq_data), scsi_cdb_string( ! csio->cdb_io.cdb_bytes, cdb_str, ! sizeof(cdb_str))); ! } ! } ! /* ! * If the sense data is a physical pointer, forget it. ! */ ! if (csio->ccb_h.flags & CAM_SENSE_PTR) { ! if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return; ! else { ! /* ! * XXX KDM this is stupid, but casting the ! * structure doesn't work... ! */ ! bcopy(&csio->sense_data, sense, ! sizeof(struct scsi_sense_data *)); ! } } else { ! /* ! * If the physical sense flag is set, but the sense pointer ! * is not also set, we assume that the user is an idiot and ! * return. (Well, okay, it could be that somehow, the ! * entire csio is physical, but we would have probably core ! * dumped on one of the bogus pointer deferences above ! * already.) ! */ ! if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return; ! else ! sense = &csio->sense_data; } ! xpt_print_path(csio->ccb_h.path); ! error_code = sense->error_code & SSD_ERRCODE; ! sense_key = sense->flags & SSD_KEY; - switch (error_code) { - case SSD_DEFERRED_ERROR: - printf("Deferred Error: "); - /* FALLTHROUGH */ - case SSD_CURRENT_ERROR: ! printf("%s", scsi_sense_key_text[sense_key]); ! info = scsi_4btoul(sense->info); ! ! if (sense->error_code & SSD_ERRCODE_VALID) { ! ! switch (sense_key) { ! case SSD_KEY_NOT_READY: ! case SSD_KEY_ILLEGAL_REQUEST: ! case SSD_KEY_UNIT_ATTENTION: ! case SSD_KEY_DATA_PROTECT: ! break; ! case SSD_KEY_BLANK_CHECK: ! printf(" req sz: %d (decimal)", ! info); ! break; ! default: ! if (info) { ! if (sense->flags & SSD_ILI) { ! printf(" ILI (length mismatch):" ! " %d", info); ! } else { ! printf(" info:%x", info); ! } ! } ! } ! } else if (info) ! printf(" info?:%x", info); ! ! if (sense->extra_len >= 4) { ! if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) { ! printf(" csi:%x,%x,%x,%x", ! sense->cmd_spec_info[0], ! sense->cmd_spec_info[1], ! sense->cmd_spec_info[2], ! sense->cmd_spec_info[3]); ! } ! } ! ! asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; ! ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; ! ! if (asc || ascq) { ! const char *desc = scsi_sense_desc(asc, ascq, ! &cgd.inq_data); ! printf(" asc:%x,%x\n", asc, ascq); ! ! xpt_print_path(csio->ccb_h.path); ! printf("%s", desc); ! } ! ! if (sense->extra_len >= 7 && sense->fru) { ! printf(" field replaceable unit: %x", sense->fru); ! } ! ! if ((sense->extra_len >= 10) ! && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) { ! printf(" sks:%x,%x", sense->sense_key_spec[0], ! scsi_2btoul(&sense->sense_key_spec[1])); ! } ! break; ! ! default: ! printf("error code %d", ! sense->error_code & SSD_ERRCODE); ! if (sense->error_code & SSD_ERRCODE_VALID) { ! printf(" at block no. %d (decimal)", ! info = scsi_4btoul(sense->info)); ! } ! } ! ! printf("\n"); ! } ! #else /* !_KERNEL */ ! ! ! char * ! scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio, ! char *str, int str_len) { struct scsi_sense_data *sense; u_int32_t info; int error_code; int sense_key; int asc, ascq; - u_int8_t command_print; char path_str[64]; - char tmpstr[2048]; - int tmpstrlen = 2048; - int cur_len = 0, tmplen = 0, retlen; ! if ((device == NULL) || (csio == NULL) || (str == NULL)) ! return(NULL); - if (str_len <= 0) - return(NULL); - /* * If the CDB is a physical address, we can't deal with it.. */ if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) ! command_print = 0; ! else ! command_print = 1; ! cam_path_string(device, path_str, 64); ! str[0] = '\0'; ! sense = NULL; ! if (command_print != 0) { ! char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; ! retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str); ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; ! if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { ! retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", ! scsi_op_desc(csio->cdb_io.cdb_ptr[0], ! &device->inq_data), ! scsi_cdb_string(csio->cdb_io.cdb_ptr, ! cdb_str, ! sizeof(cdb_str))); ! } else { ! retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", ! scsi_op_desc(csio->cdb_io.cdb_bytes[0], ! &device->inq_data), scsi_cdb_string( ! csio->cdb_io.cdb_bytes, cdb_str, ! sizeof(cdb_str))); ! } ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; } /* --- 1795,1903 ---- if (cgd.ccb_h.status == CAM_DEV_NOT_THERE) cgd.inq_data.device = T_DIRECT; ! inq_data = &cgd.inq_data; ! ! #else /* !_KERNEL */ ! inq_data = &device->inq_data; ! #endif /* _KERNEL/!_KERNEL */ ! if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { ! sbuf_printf(sb, "%s. CDB: %s", ! scsi_op_desc(csio->cdb_io.cdb_ptr[0], inq_data), ! scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str, ! sizeof(cdb_str))); } else { ! sbuf_printf(sb, "%s. CDB: %s", ! scsi_op_desc(csio->cdb_io.cdb_bytes[0], inq_data), ! scsi_cdb_string(csio->cdb_io.cdb_bytes, cdb_str, ! sizeof(cdb_str))); } ! return(0); ! } ! /* ! * scsi_sense_sbuf() returns 0 for success and -1 for failure. ! */ ! #ifdef _KERNEL ! int ! scsi_sense_sbuf(struct ccb_scsiio *csio, struct sbuf *sb, ! scsi_sense_string_flags flags) #else /* !_KERNEL */ ! int ! scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio, ! struct sbuf *sb, scsi_sense_string_flags flags) ! #endif /* _KERNEL/!_KERNEL */ { struct scsi_sense_data *sense; + struct scsi_inquiry_data *inq_data; + #ifdef _KERNEL + struct ccb_getdev cgd; + #endif /* _KERNEL */ u_int32_t info; int error_code; int sense_key; int asc, ascq; char path_str[64]; ! #ifndef _KERNEL ! if (device == NULL) ! return(-1); ! #endif /* !_KERNEL */ ! if ((csio == NULL) || (sb == NULL)) ! return(-1); /* * If the CDB is a physical address, we can't deal with it.. */ if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) ! flags &= ~SSS_FLAG_PRINT_COMMAND; ! ! #ifdef _KERNEL ! xpt_path_string(csio->ccb_h.path, path_str, sizeof(path_str)); ! #else /* !_KERNEL */ ! cam_path_string(device, path_str, sizeof(path_str)); ! #endif /* _KERNEL/!_KERNEL */ ! #ifdef _KERNEL ! /* ! * Get the device information. ! */ ! xpt_setup_ccb(&cgd.ccb_h, ! csio->ccb_h.path, ! /*priority*/ 1); ! cgd.ccb_h.func_code = XPT_GDEV_TYPE; ! xpt_action((union ccb *)&cgd); ! /* ! * If the device is unconfigured, just pretend that it is a hard ! * drive. scsi_op_desc() needs this. ! */ ! if (cgd.ccb_h.status == CAM_DEV_NOT_THERE) ! cgd.inq_data.device = T_DIRECT; ! inq_data = &cgd.inq_data; ! #else /* !_KERNEL */ ! inq_data = &device->inq_data; ! #endif /* _KERNEL/!_KERNEL */ ! sense = NULL; ! if (flags & SSS_FLAG_PRINT_COMMAND) { ! sbuf_cat(sb, path_str); ! #ifdef _KERNEL ! scsi_command_string(csio, sb); ! #else /* !_KERNEL */ ! scsi_command_string(device, csio, sb); ! #endif /* _KERNEL/!_KERNEL */ } /* *************** *** 1862,1872 **** */ if (csio->ccb_h.flags & CAM_SENSE_PTR) { if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return(NULL); else { /* ! * XXX KDM this is stupid, but casting the ! * structure doesn't work... */ bcopy(&csio->sense_data, sense, sizeof(struct scsi_sense_data *)); --- 1905,1916 ---- */ if (csio->ccb_h.flags & CAM_SENSE_PTR) { if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return(-1); else { /* ! * bcopy the pointer to avoid unaligned access ! * errors on finicky architectures. We don't ! * ensure that the sense data is pointer aligned. */ bcopy(&csio->sense_data, sense, sizeof(struct scsi_sense_data *)); *************** *** 1881,1926 **** * already.) */ if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return(NULL); else sense = &csio->sense_data; } ! retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str); ! ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; - strncat(str, tmpstr, tmplen); - cur_len += retlen; - str[str_len - 1] = '\0'; - error_code = sense->error_code & SSD_ERRCODE; sense_key = sense->flags & SSD_KEY; switch (error_code) { case SSD_DEFERRED_ERROR: ! retlen = snprintf(tmpstr, tmpstrlen, "Deferred Error: "); ! ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; - strncat(str, tmpstr, tmplen); - cur_len += retlen; - str[str_len - 1] = '\0'; /* FALLTHROUGH */ case SSD_CURRENT_ERROR: ! retlen = snprintf(tmpstr, tmpstrlen, "%s", ! scsi_sense_key_text[sense_key]); ! ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; info = scsi_4btoul(sense->info); --- 1925,1956 ---- * already.) */ if (csio->ccb_h.flags & CAM_SENSE_PHYS) ! return(-1); else sense = &csio->sense_data; } ! sbuf_cat(sb, path_str); error_code = sense->error_code & SSD_ERRCODE; sense_key = sense->flags & SSD_KEY; switch (error_code) { case SSD_DEFERRED_ERROR: ! sbuf_printf(sb, "Deferred Error: "); /* FALLTHROUGH */ case SSD_CURRENT_ERROR: + { + const char *sense_key_desc; + const char *asc_desc; ! asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; ! ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; ! scsi_sense_desc(sense_key, asc, ascq, inq_data, ! &sense_key_desc, &asc_desc); ! sbuf_cat(sb, sense_key_desc); info = scsi_4btoul(sense->info); *************** *** 1933,2295 **** case SSD_KEY_DATA_PROTECT: break; case SSD_KEY_BLANK_CHECK: ! retlen = snprintf(tmpstr, tmpstrlen, ! " req sz: %d (decimal)", ! info); ! ! if ((tmplen = str_len - cur_len - 1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; break; default: if (info) { if (sense->flags & SSD_ILI) { ! retlen = snprintf (tmpstr, ! tmpstrlen, ! " ILI (length " "mismatch): %d", info); } else { ! retlen = snprintf(tmpstr, ! tmpstrlen, ! " info:%x", ! info); } - - if ((tmplen = str_len - cur_len -1) < 0) - goto sst_bailout; - - strncat(str, tmpstr, tmplen); - cur_len += retlen; - str[str_len - 1] = '\0'; } } } else if (info) { ! retlen = snprintf(tmpstr, tmpstrlen," info?:%x", info); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; } if (sense->extra_len >= 4) { if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) { ! retlen = snprintf(tmpstr, tmpstrlen, ! " csi:%x,%x,%x,%x", ! sense->cmd_spec_info[0], ! sense->cmd_spec_info[1], ! sense->cmd_spec_info[2], ! sense->cmd_spec_info[3]); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; } } - asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; - ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; - if (asc || ascq) { ! const char *desc = scsi_sense_desc(asc, ascq, ! &device->inq_data); ! retlen = snprintf(tmpstr, tmpstrlen, ! " asc:%x,%x\n%s%s", asc, ascq, ! path_str, desc); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; } if (sense->extra_len >= 7 && sense->fru) { ! retlen = snprintf(tmpstr, tmpstrlen, ! " field replaceable unit: %x", ! sense->fru); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! str[str_len - 1] = '\0'; ! cur_len += retlen; } if ((sense->extra_len >= 10) && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) { ! retlen = snprintf(tmpstr, tmpstrlen, " sks:%x,%x", ! sense->sense_key_spec[0], ! scsi_2btoul(&sense->sense_key_spec[1])); ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! strncat(str, tmpstr, tmplen); ! str[str_len - 1] = '\0'; ! cur_len += retlen; } break; default: ! retlen = snprintf(tmpstr, tmpstrlen, "error code %d", ! sense->error_code & SSD_ERRCODE); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; if (sense->error_code & SSD_ERRCODE_VALID) { ! retlen = snprintf(tmpstr, tmpstrlen, ! " at block no. %d (decimal)", ! info = scsi_4btoul(sense->info)); ! ! if ((tmplen = str_len - cur_len -1) < 0) ! goto sst_bailout; ! ! strncat(str, tmpstr, tmplen); ! cur_len += retlen; ! str[str_len - 1] = '\0'; } } ! retlen = snprintf(tmpstr, tmpstrlen, "\n"); - if ((tmplen = str_len - cur_len -1) < 0) - goto sst_bailout; - strncat(str, tmpstr, tmplen); - cur_len += retlen; - str[str_len - 1] = '\0'; ! sst_bailout: ! return(str); ! } ! void ! scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, ! FILE *ofile) ! { ! char str[2048]; ! if ((device == NULL) || (csio == NULL) || (ofile == NULL)) ! return; ! fprintf(ofile, "%s", scsi_sense_string(device, csio, str, 2048)); } - #endif /* _KERNEL/!_KERNEL */ - #ifdef _KERNEL ! int ! scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags, ! u_int32_t *relsim_flags, u_int32_t *openings, ! u_int32_t *timeout, scsi_sense_action error_action) ! #else ! int ! scsi_interpret_sense(struct cam_device *device, union ccb *ccb, ! u_int32_t sense_flags, u_int32_t *relsim_flags, ! u_int32_t *openings, u_int32_t *timeout, ! scsi_sense_action error_action) ! #endif { ! struct scsi_sense_data *sense; ! int error_code, sense_key, asc, ascq; ! int error; ! int print_sense; ! struct ccb_scsiio *csio; ! int retry; ! csio = &ccb->csio; ! sense = &csio->sense_data; ! scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); ! #ifdef _KERNEL ! if (bootverbose) { ! sense_flags |= SF_PRINT_ALWAYS; ! print_sense = TRUE; ! } else if ((sense_flags & SF_NO_PRINT) == 0) ! #else ! if ((sense_flags & SF_NO_PRINT) == 0) ! #endif ! print_sense = TRUE; ! else ! print_sense = FALSE; ! switch (error_code) { ! case SSD_DEFERRED_ERROR: ! { ! /* ! * XXX dufault@FreeBSD.org ! * This error doesn't relate to the command associated ! * with this request sense. A deferred error is an error ! * for a command that has already returned GOOD status ! * (see 8.2.14.2). ! * ! * By my reading of that section, it looks like the current ! * command has been cancelled, we should now clean things up ! * (hopefully recovering any lost data) and then retry the ! * current command. There are two easy choices, both wrong: ! * ! * 1. Drop through (like we had been doing), thus treating ! * this as if the error were for the current command and ! * return and stop the current command. ! * ! * 2. Issue a retry (like I made it do) thus hopefully ! * recovering the current transfer, and ignoring the ! * fact that we've dropped a command. ! * ! * These should probably be handled in a device specific ! * sense handler or punted back up to a user mode daemon ! */ ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! break; ! } ! case SSD_CURRENT_ERROR: ! { ! ! switch (sense_key) { ! case SSD_KEY_NO_SENSE: ! /* Why were we called then? Well don't bail now */ ! /* FALLTHROUGH */ ! case SSD_KEY_EQUAL: ! /* These should be filtered by the peripheral drivers */ ! print_sense = FALSE; ! /* FALLTHROUGH */ ! case SSD_KEY_MISCOMPARE: ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! error = ERESTART; ! ccb->ccb_h.retry_count--; ! } else { ! error = EIO; ! } ! case SSD_KEY_RECOVERED_ERROR: ! error = 0; /* not an error */ ! break; ! case SSD_KEY_ILLEGAL_REQUEST: ! if (((sense_flags & SF_QUIET_IR) != 0) ! && ((sense_flags & SF_PRINT_ALWAYS) == 0)) ! print_sense = FALSE; ! error = EINVAL; ! break; ! case SSD_KEY_NOT_READY: ! case SSD_KEY_DATA_PROTECT: ! case SSD_KEY_VOLUME_OVERFLOW: ! case SSD_KEY_BLANK_CHECK: /* should be filtered out by ! peripheral drivers */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! print_sense = FALSE; ! } else { ! if (((error_action & SSQ_PRINT_SENSE) == 0) ! && ((sense_flags & SF_PRINT_ALWAYS) == 0)) ! print_sense = FALSE; ! error = error_action & SS_ERRMASK; ! } ! break; ! case SSD_KEY_UNIT_ATTENTION: ! /* ! * This should also be filtered out by ! * peripheral drivers since each has a different ! * concept of what it means to invalidate the media. ! */ ! if ((sense_flags & SF_RETRY_UA) != 0) { ! /* don't decrement retry count */ ! error = ERESTART; ! print_sense = FALSE; ! } else { ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! print_sense = FALSE; ! } else { ! if (((error_action & ! SSQ_PRINT_SENSE) == 0) ! && ((sense_flags & ! SF_PRINT_ALWAYS) == 0)) ! print_sense = FALSE; ! error = error_action & SS_ERRMASK; ! } ! } ! break; ! case SSD_KEY_ABORTED_COMMAND: ! default: ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! print_sense = FALSE; ! } else { ! if (((error_action & SSQ_PRINT_SENSE) == 0) ! && ((sense_flags & SF_PRINT_ALWAYS) == 0)) ! print_sense = FALSE; ! error = error_action & SS_ERRMASK; ! } ! /* ! * Make sure ABORTED COMMAND errors get ! * printed as they're indicative of marginal ! * SCSI busses that people should address. ! */ ! if (sense_key == SSD_KEY_ABORTED_COMMAND) ! print_sense = TRUE; ! } ! break; ! } ! default: ! /* decrement the number of retries */ ! retry = ccb->ccb_h.retry_count > 0; ! if (retry) { ! ccb->ccb_h.retry_count--; ! error = ERESTART; ! print_sense = FALSE; ! } else ! error = EIO; ! break; ! } ! if (print_sense) { ! #ifdef _KERNEL ! scsi_sense_print(csio); ! #else ! scsi_sense_print(device, csio, stdout); ! #endif ! } ! ! return (error); } /* * This function currently requires at least 36 bytes, or * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this --- 1963,2131 ---- case SSD_KEY_DATA_PROTECT: break; case SSD_KEY_BLANK_CHECK: ! sbuf_printf(sb, " req sz: %d (decimal)", info); break; default: if (info) { if (sense->flags & SSD_ILI) { ! sbuf_printf(sb, " ILI (length " "mismatch): %d", info); } else { ! sbuf_printf(sb, " info:%x", ! info); } } } } else if (info) { ! sbuf_printf(sb, " info?:%x", info); } if (sense->extra_len >= 4) { if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) { ! sbuf_printf(sb, " csi:%x,%x,%x,%x", ! sense->cmd_spec_info[0], ! sense->cmd_spec_info[1], ! sense->cmd_spec_info[2], ! sense->cmd_spec_info[3]); } } if (asc || ascq) { ! sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq, ! path_str, asc_desc); } if (sense->extra_len >= 7 && sense->fru) { ! sbuf_printf(sb, " field replaceable unit: %x", ! sense->fru); } if ((sense->extra_len >= 10) && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) { ! switch(sense_key) { ! case SSD_KEY_ILLEGAL_REQUEST: { ! int bad_command; ! char tmpstr2[40]; ! ! if (sense->sense_key_spec[0] & 0x40) ! bad_command = 1; ! else ! bad_command = 0; ! tmpstr2[0] = '\0'; ! /* Bit pointer is valid */ ! if (sense->sense_key_spec[0] & 0x08) ! snprintf(tmpstr2, sizeof(tmpstr2), ! "bit %d", ! sense->sense_key_spec[0] & 0x7); ! sbuf_printf(sb, ! ": %s byte %d %s is invalid", ! bad_command ? ! "Command" : "Data", ! scsi_2btoul( ! &sense->sense_key_spec[1]), ! tmpstr2); ! break; ! } ! case SSD_KEY_RECOVERED_ERROR: ! case SSD_KEY_HARDWARE_ERROR: ! case SSD_KEY_MEDIUM_ERROR: ! sbuf_printf(sb, " actual retry count: %d", ! scsi_2btoul( ! &sense->sense_key_spec[1])); ! break; ! default: ! sbuf_printf(sb, " sks:%#x,%#x", ! sense->sense_key_spec[0], ! scsi_2btoul( ! &sense->sense_key_spec[1])); ! break; ! } } break; + } default: ! sbuf_printf(sb, "error code %d", ! sense->error_code & SSD_ERRCODE); if (sense->error_code & SSD_ERRCODE_VALID) { ! sbuf_printf(sb, " at block no. %d (decimal)", ! info = scsi_4btoul(sense->info)); } } ! sbuf_printf(sb, "\n"); ! ! return(0); ! } ! #ifdef _KERNEL ! char * ! scsi_sense_string(struct ccb_scsiio *csio, char *str, int str_len) ! #else /* !_KERNEL */ ! char * ! scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio, ! char *str, int str_len) ! #endif /* _KERNEL/!_KERNEL */ ! { ! struct sbuf sb; ! sbuf_new(&sb, str, str_len, 0); ! #ifdef _KERNEL ! scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND); ! #else /* !_KERNEL */ ! scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND); ! #endif /* _KERNEL/!_KERNEL */ ! sbuf_finish(&sb); ! return(sbuf_data(&sb)); } #ifdef _KERNEL ! void ! scsi_sense_print(struct ccb_scsiio *csio) { ! struct sbuf sb; ! char str[512]; ! sbuf_new(&sb, str, sizeof(str), 0); ! scsi_sense_sbuf(csio, &sb, SSS_FLAG_PRINT_COMMAND); ! sbuf_finish(&sb); ! printf("%s", sbuf_data(&sb)); ! } ! #else /* !_KERNEL */ ! void ! scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, ! FILE *ofile) ! { ! struct sbuf sb; ! char str[512]; ! if ((device == NULL) || (csio == NULL) || (ofile == NULL)) ! return; ! sbuf_new(&sb, str, sizeof(str), 0); ! scsi_sense_sbuf(device, csio, &sb, SSS_FLAG_PRINT_COMMAND); ! sbuf_finish(&sb); ! fprintf(ofile, "%s", sbuf_data(&sb)); } + #endif /* _KERNEL/!_KERNEL */ + /* * This function currently requires at least 36 bytes, or * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this *************** *** 2849,2855 **** bzero(scsi_cmd, sizeof(*scsi_cmd)); scsi_cmd->opcode = START_STOP_UNIT; if (start != 0) { ! scsi_cmd->how |= SSS_START; /* it takes a lot of power to start a drive */ extra_flags |= CAM_HIGH_POWER; } --- 2685,2691 ---- bzero(scsi_cmd, sizeof(*scsi_cmd)); scsi_cmd->opcode = START_STOP_UNIT; if (start != 0) { ! scsi_cmd->how |= SS_START; /* it takes a lot of power to start a drive */ extra_flags |= CAM_HIGH_POWER; } *** src/sys/cam/scsi/scsi_all.h.orig --- src/sys/cam/scsi/scsi_all.h *************** *** 92,107 **** 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_MASK = 0xff0000 } scsi_sense_action; --- 92,99 ---- SS_TUR = 0x040000, /* Send a Test Unit Ready command to the * device, then retry the original command. */ ! SS_REQSENSE = 0x050000, /* Send a RequestSense command to the ! * device, then retry the original command. */ SS_MASK = 0xff0000 } scsi_sense_action; *************** *** 111,126 **** 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. */ SSQ_PRINT_SENSE = 0x0800, SSQ_MASK = 0xff00 --- 103,112 ---- SSQ_DECREMENT_COUNT = 0x0100, /* Decrement the retry count */ SSQ_MANY = 0x0200, /* send lots of recovery commands */ SSQ_RANGE = 0x0400, /* ! * 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,142 **** /* 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 ! /* Default error action, without an error return value */ ! #define SS_NEDEF 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 struct scsi_generic { --- 115,128 ---- /* Mask for error status values */ #define SS_ERRMASK 0xff ! /* The default, retyable, error action */ ! #define SS_RDEF SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE|EIO ! /* The retyable, error action, with table specified error code */ ! #define SS_RET SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE ! /* Fatal error action, with table specified error code */ ! #define SS_FATAL SS_FAIL|SSQ_PRINT_SENSE struct scsi_generic { *************** *** 493,499 **** 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 * type is currently connected to * logical unit. If the target cannot * determine whether or not a physical --- 479,486 ---- 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 * type is currently connected to * logical unit. If the target cannot * determine whether or not a physical *************** *** 504,517 **** * 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 * 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 * supporting a physical device on * this logical unit. For this * peripheral qualifier the peripheral --- 491,506 ---- * 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 * 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 * supporting a physical device on * this logical unit. For this * peripheral qualifier the peripheral *************** *** 531,537 **** #define SCSI_REV_0 0 #define SCSI_REV_CCS 1 #define SCSI_REV_2 2 ! #define SCSI_REV_3 3 #define SCSI_REV_SPC2 4 #define SID_ECMA 0x38 --- 520,526 ---- #define SCSI_REV_0 0 #define SCSI_REV_CCS 1 #define SCSI_REV_2 2 ! #define SCSI_REV_SPC 3 #define SCSI_REV_SPC2 4 #define SID_ECMA 0x38 *************** *** 569,574 **** --- 558,564 ---- #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,710 **** #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_QUEUE_FULL 0x28 struct scsi_inquiry_pattern { u_int8_t type; --- 693,702 ---- #define SCSI_STATUS_INTERMED 0x10 #define SCSI_STATUS_INTERMED_COND_MET 0x14 #define SCSI_STATUS_RESERV_CONFLICT 0x18 ! #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,742 **** struct scsi_sense_quirk_entry { struct scsi_inquiry_pattern inq_pat; int num_ascs; struct asc_table_entry *asc_info; }; 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 { --- 718,740 ---- 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; const char *desc; }; struct op_table_entry { *************** *** 751,756 **** --- 749,758 ---- 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,772 **** extern const char *scsi_sense_key_text[]; __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); #ifdef _KERNEL void scsi_sense_print(struct ccb_scsiio *csio); int scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags, --- 763,784 ---- extern const char *scsi_sense_key_text[]; + struct sbuf; + __BEGIN_DECLS ! 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,780 **** u_int32_t *reduction, u_int32_t *timeout, scsi_sense_action error_action); ! #else char * scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio, char *str, int str_len); --- 786,797 ---- u_int32_t *reduction, u_int32_t *timeout, scsi_sense_action error_action); ! #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,799 **** #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, --- 810,815 ---- *** src/sys/cam/scsi/scsi_cd.c.orig --- src/sys/cam/scsi/scsi_cd.c *************** *** 1559,1568 **** else sf = 0; ! /* Retry selection timeouts */ ! sf |= SF_RETRY_SELTO; ! ! if ((error = cderror(done_ccb, 0, sf)) == ERESTART) { /* * A retry was scheuled, so * just return. --- 1559,1566 ---- else sf = 0; ! error = cderror(done_ccb, CAM_RETRY_SELTO, sf); ! if (error == ERESTART) { /* * A retry was scheuled, so * just return. *************** *** 1661,1668 **** * 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); if (error == ERESTART) { /* * A retry was scheuled, so --- 1659,1666 ---- * Retry any UNIT ATTENTION type errors. They * are expected at boot. */ ! error = cderror(done_ccb, CAM_RETRY_SELTO, ! SF_RETRY_UA | SF_NO_PRINT); if (error == ERESTART) { /* * A retry was scheuled, so *************** *** 1713,1727 **** * supported" (0x25) error. */ if ((have_sense) && (asc != 0x25) ! && (error_code == SSD_CURRENT_ERROR)) 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) { /* * We only print out an error for * CDROM type devices. For WORM --- 1711,1731 ---- * supported" (0x25) error. */ if ((have_sense) && (asc != 0x25) ! && (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", ! 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 *************** *** 2491,2498 **** SSD_FULL_SIZE, /* timeout */60000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 2495,2502 ---- SSD_FULL_SIZE, /* timeout */60000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT); xpt_release_ccb(ccb); *************** *** 2535,2542 **** SSD_FULL_SIZE, /* timeout */20000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT|SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 2539,2546 ---- SSD_FULL_SIZE, /* timeout */20000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA|SF_NO_PRINT); xpt_release_ccb(ccb); *************** *** 2696,2703 **** scsi_cmd->op_code = READ_TOC; ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA|SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 2700,2707 ---- scsi_cmd->op_code = READ_TOC; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2743,2750 **** 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); xpt_release_ccb(ccb); --- 2747,2754 ---- scsi_ulto2b(len, (u_int8_t *)scsi_cmd->data_len); scsi_cmd->control = 0; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2783,2790 **** 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); xpt_release_ccb(ccb); --- 2787,2794 ---- scsi_cmd->length = sizeof(*data) & 0xff; scsi_cmd->opcode = MODE_SENSE; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2830,2837 **** */ data->header.medium_type = 0; ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 2834,2841 ---- */ data->header.medium_type = 0; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2886,2893 **** cdb_len, /*timeout*/50 * 1000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 2890,2897 ---- cdb_len, /*timeout*/50 * 1000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2931,2938 **** 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); xpt_release_ccb(ccb); --- 2935,2942 ---- scsi_cmd->end_s = ends; scsi_cmd->end_f = endf; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 2975,2982 **** 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); xpt_release_ccb(ccb); --- 2979,2986 ---- scsi_cmd->end_track = etrack; scsi_cmd->end_index = eindex; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 3014,3021 **** scsi_cmd->op_code = PAUSE; scsi_cmd->resume = go; ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA |SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 3018,3025 ---- scsi_cmd->op_code = PAUSE; scsi_cmd->resume = go; ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 3042,3049 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 3046,3053 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 3070,3077 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); xpt_release_ccb(ccb); --- 3074,3081 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); xpt_release_ccb(ccb); *************** *** 3141,3148 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); if (error != 0) goto bailout; --- 3145,3152 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); if (error != 0) goto bailout; *************** *** 3318,3325 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); bailout: --- 3322,3329 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); bailout: *************** *** 3450,3457 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | SF_RETRY_SELTO); if (error != 0) goto bailout; --- 3454,3461 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ 50000); ! error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA); if (error != 0) goto bailout; *** src/sys/cam/scsi/scsi_ch.c.orig --- src/sys/cam/scsi/scsi_ch.c *************** *** 618,625 **** } else { int error; ! error = cherror(done_ccb, 0, SF_RETRY_UA | ! SF_NO_PRINT | SF_RETRY_SELTO); /* * Retry any UNIT ATTENTION type errors. They * are expected at boot. --- 618,625 ---- } else { int error; ! error = cherror(done_ccb, CAM_RETRY_SELTO, ! SF_RETRY_UA | SF_NO_PRINT); /* * Retry any UNIT ATTENTION type errors. They * are expected at boot. *************** *** 869,876 **** /* 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, &softc->device_stats); xpt_release_ccb(ccb); --- 869,876 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_MOVE_MEDIUM); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); xpt_release_ccb(ccb); *************** *** 932,939 **** /* 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, &softc->device_stats); xpt_release_ccb(ccb); --- 932,939 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_EXCHANGE_MEDIUM); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); xpt_release_ccb(ccb); *************** *** 978,985 **** /* 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, &softc->device_stats); xpt_release_ccb(ccb); --- 978,985 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_POSITION_TO_ELEMENT); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); xpt_release_ccb(ccb); *************** *** 1134,1141 **** /* 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, &softc->device_stats); if (error) --- 1134,1141 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); if (error) *************** *** 1170,1177 **** /* 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, &softc->device_stats); if (error) --- 1170,1177 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_READ_ELEMENT_STATUS); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); if (error) *************** *** 1249,1256 **** /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ 0, ! /*sense_flags*/ SF_RETRY_UA | SF_RETRY_SELTO, &softc->device_stats); xpt_release_ccb(ccb); --- 1249,1256 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); xpt_release_ccb(ccb); *************** *** 1336,1343 **** /* 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, &softc->device_stats); xpt_release_ccb(ccb); --- 1336,1343 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_SEND_VOLTAG); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); xpt_release_ccb(ccb); *************** *** 1400,1408 **** /* 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); if (error) { --- 1400,1407 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_MODE_SENSE); ! error = cam_periph_runccb(ccb, cherror, /*cam_flags*/ CAM_RETRY_SELTO, ! /* sense_flags */ SF_RETRY_UA|SF_NO_PRINT, &softc->device_stats); if (error) { *************** *** 1413,1421 **** 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, &softc->device_stats); } else { /* --- 1412,1420 ---- ccb->csio.cdb_io.cdb_bytes; sms->byte2 &= ~SMS_DBD; ! error = cam_periph_runccb(ccb, cherror, ! /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); } else { /* *************** *** 1464,1472 **** /* 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); if (error) { if (dbd) { --- 1463,1471 ---- /* sense_len */ SSD_FULL_SIZE, /* timeout */ CH_TIMEOUT_MODE_SENSE); ! 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) { *************** *** 1476,1484 **** 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, &softc->device_stats); } else { /* --- 1475,1483 ---- ccb->csio.cdb_io.cdb_bytes; sms->byte2 &= ~SMS_DBD; ! error = cam_periph_runccb(ccb, cherror, ! /*cam_flags*/ CAM_RETRY_SELTO, ! /*sense_flags*/ SF_RETRY_UA, &softc->device_stats); } else { /* *** src/sys/cam/scsi/scsi_da.c.orig --- src/sys/cam/scsi/scsi_da.c *************** *** 337,342 **** --- 337,344 ---- 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; *************** *** 344,352 **** unit = dkunit(dev); part = dkpart(dev); periph = cam_extend_get(daperiphs, unit); ! if (periph == NULL) return (ENXIO); softc = (struct da_softc *)periph->softc; --- 346,357 ---- unit = dkunit(dev); part = dkpart(dev); + s = splsoftcam(); periph = cam_extend_get(daperiphs, unit); ! if (periph == NULL) { ! splx(s); return (ENXIO); + } softc = (struct da_softc *)periph->softc; *************** *** 354,368 **** ("daopen: dev=%s (unit %d , partition %d)\n", devtoname(dev), unit, part)); ! 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); --- 359,371 ---- ("daopen: dev=%s (unit %d , partition %d)\n", devtoname(dev), unit, part)); ! 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; if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) { /* Invalidate our pack information. */ disk_invalidate(&softc->disk); *************** *** 371,407 **** 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); ! 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; ! error = cam_periph_runccb(ccb, daerror, /*cam_flags*/0, ! /*sense_flags*/SF_RETRY_UA | ! SF_RETRY_SELTO, ! &softc->device_stats); ! xpt_release_ccb(ccb); ! if (error == 0) { ! dasetgeom(periph, rcap); ! } ! free(rcap, M_TEMP); ! } if (error == 0) { struct ccb_getdev cgd; --- 374,410 ---- splx(s); /* Do a read capacity */ ! 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*/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*/CAM_RETRY_SELTO, ! /*sense_flags*/SF_RETRY_UA, ! &softc->device_stats); ! 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); ! free(rcap, M_TEMP); if (error == 0) { struct ccb_getdev cgd; *************** *** 432,441 **** * 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 --- 435,440 ---- *************** *** 447,456 **** } } ! if (error != 0) { ! if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) { ! daprevent(periph, PR_ALLOW); ! } } cam_periph_unlock(periph); return (error); --- 446,454 ---- } } ! if (error == 0) { ! if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0) ! daprevent(periph, PR_PREVENT); } cam_periph_unlock(periph); return (error); *************** *** 1224,1233 **** else sf = 0; ! /* Retry selection timeouts */ ! sf |= SF_RETRY_SELTO; ! ! if ((error = daerror(done_ccb, 0, sf)) == ERESTART) { /* * A retry was scheuled, so * just return. --- 1222,1229 ---- else sf = 0; ! error = daerror(done_ccb, CAM_RETRY_SELTO, sf); ! if (error == ERESTART) { /* * A retry was scheuled, so * just return. *************** *** 1284,1289 **** --- 1280,1287 ---- /*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; *************** *** 1331,1338 **** * 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); if (error == ERESTART) { /* * A retry was scheuled, so --- 1329,1336 ---- * Retry any UNIT ATTENTION type errors. They * are expected at boot. */ ! error = daerror(done_ccb, CAM_RETRY_SELTO, ! SF_RETRY_UA|SF_NO_PRINT); if (error == ERESTART) { /* * A retry was scheuled, so *************** *** 1348,1360 **** 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; xpt_setup_ccb(&cgd.ccb_h, done_ccb->ccb_h.path, --- 1346,1359 ---- struct ccb_getdev cgd; /* Don't wedge this device's queue */ ! 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, *************** *** 1382,1396 **** * unit not supported" (0x25) error. */ if ((have_sense) && (asc != 0x25) ! && (error_code == SSD_CURRENT_ERROR)) 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 (have_sense) scsi_sense_print( &done_ccb->csio); --- 1381,1401 ---- * unit not supported" (0x25) error. */ if ((have_sense) && (asc != 0x25) ! && (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", ! sense_key_desc, ! asc_desc); ! } else { if (have_sense) scsi_sense_print( &done_ccb->csio); *************** *** 1414,1420 **** free(rdcap, M_TEMP); if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); ! softc->state = DA_STATE_NORMAL; /* * Since our peripheral may be invalidated by an error * above or an external event, we must release our CCB --- 1419,1425 ---- free(rdcap, M_TEMP); if (announce_buf[0] != '\0') xpt_announce_periph(periph, announce_buf); ! softc->state = DA_STATE_NORMAL; /* * Since our peripheral may be invalidated by an error * above or an external event, we must release our CCB *** src/sys/cam/scsi/scsi_pass.c.orig --- src/sys/cam/scsi/scsi_pass.c *************** *** 1,5 **** /* ! * Copyright (c) 1997, 1998 Justin T. Gibbs. * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. * All rights reserved. * --- 1,5 ---- /* ! * Copyright (c) 1997, 1998, 2000 Justin T. Gibbs. * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry. * All rights reserved. * *************** *** 42,47 **** --- 42,48 ---- #include #include #include + #include #include #include *************** *** 67,79 **** #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; }; #ifndef MIN --- 68,79 ---- #define ccb_bp ppriv_ptr1 struct pass_softc { ! 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,91 **** 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; --- 85,90 ---- *************** *** 112,123 **** static struct cdevsw pass_cdevsw = { /* open */ passopen, /* close */ passclose, ! /* read */ physread, ! /* write */ physwrite, /* ioctl */ passioctl, /* poll */ nopoll, /* mmap */ nommap, ! /* strategy */ passstrategy, /* name */ "pass", /* maj */ PASS_CDEV_MAJOR, /* dump */ nodump, --- 111,122 ---- static struct cdevsw pass_cdevsw = { /* open */ passopen, /* close */ passclose, ! /* read */ noread, ! /* write */ nowrite, /* ioctl */ passioctl, /* poll */ nopoll, /* mmap */ nommap, ! /* strategy */ nostrategy, /* name */ "pass", /* maj */ PASS_CDEV_MAJOR, /* dump */ nodump, *************** *** 173,181 **** 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; --- 172,178 ---- *************** *** 194,218 **** 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 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); --- 191,200 ---- softc->flags |= PASS_FLAG_INVALID; /* ! * XXX Return all queued I/O with ENXIO. * XXX Handle any transactions queued to the card * with XPT_ABORT_CCB. */ if (bootverbose) { xpt_print_path(periph->path); *************** *** 268,276 **** passasync, AC_FOUND_DEVICE, cgd); if (status != CAM_REQ_CMP ! && status != CAM_REQ_INPROG) printf("passasync: Unable to attach new device " ! "due to status 0x%x\n", status); break; } --- 250,264 ---- passasync, AC_FOUND_DEVICE, cgd); if (status != CAM_REQ_CMP ! && 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 %#x: %s\n", status, entry ? ! entry->status_text : "Unknown"); ! } break; } *************** *** 286,291 **** --- 274,280 ---- struct pass_softc *softc; struct ccb_setasync csa; struct ccb_getdev *cgd; + int no_tags; cgd = (struct ccb_getdev *)arg; if (periph == NULL) { *************** *** 310,327 **** 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, softc->pd_type | DEVSTAT_TYPE_IF_SCSI | DEVSTAT_TYPE_PASS, --- 299,317 ---- bzero(softc, sizeof(*softc)); softc->state = PASS_STATE_NORMAL; softc->pd_type = SID_TYPE(&cgd->inq_data); 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. */ ! 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, *************** *** 448,523 **** 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) { struct pass_softc *softc; --- 438,444 ---- *************** *** 527,579 **** 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); ! } break; } - } } static void passdone(struct cam_periph *periph, union ccb *done_ccb) { --- 448,464 ---- switch (softc->state) { case PASS_STATE_NORMAL: s = splbio(); ! 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) { *************** *** 583,637 **** 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); } --- 468,478 ---- *************** *** 792,799 **** 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, &softc->device_stats); if (need_unmap != 0) --- 633,640 ---- error = cam_periph_runccb(ccb, (ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? passerror : NULL, ! /* cam_flags */ CAM_RETRY_SELTO, ! /* sense_flags */SF_RETRY_UA, &softc->device_stats); if (need_unmap != 0) *** src/sys/cam/scsi/scsi_pass.h.orig --- src/sys/cam/scsi/scsi_pass.h *************** *** 32,37 **** --- 32,41 ---- #include + /* + * 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) *** src/sys/cam/scsi/scsi_pt.c.orig --- src/sys/cam/scsi/scsi_pt.c *************** *** 595,603 **** else sf = 0; ! sf |= SF_RETRY_SELTO; ! ! if ((error = pterror(done_ccb, 0, sf)) == ERESTART) { /* * A retry was scheuled, so * just return. --- 595,602 ---- else sf = 0; ! error = pterror(done_ccb, CAM_RETRY_SELTO, sf); ! if (error == ERESTART) { /* * A retry was scheuled, so * just return. *** src/sys/cam/scsi/scsi_sa.c.orig --- src/sys/cam/scsi/scsi_sa.c *************** *** 1907,1914 **** 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, &softc->device_stats); QFRLS(ccb); if (error) { --- 1907,1914 ---- QFRLS(ccb); scsi_rewind(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT); ! error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO, ! SF_NO_PRINT | SF_RETRY_UA, &softc->device_stats); QFRLS(ccb); if (error) { *************** *** 1925,1933 **** 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); QFRLS(ccb); xpt_release_ccb(ccb); --- 1925,1933 ---- scsi_read_block_limits(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, rblim, SSD_FULL_SIZE, 5000); ! error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO, ! SF_NO_PRINT | SF_RETRY_UA, &softc->device_stats); ! QFRLS(ccb); xpt_release_ccb(ccb); *************** *** 1941,1947 **** softc->max_blk = ~0; softc->min_blk = 0; } else { ! if (softc->scsi_rev >= SCSI_REV_3) { softc->blk_gran = RBL_GRAN(rblim); } else { softc->blk_gran = 0; --- 1941,1947 ---- softc->max_blk = ~0; softc->min_blk = 0; } else { ! if (softc->scsi_rev >= SCSI_REV_SPC) { softc->blk_gran = RBL_GRAN(rblim); } else { softc->blk_gran = 0; *** src/sys/cam/scsi/scsi_ses.c.orig --- src/sys/cam/scsi/scsi_ses.c *************** *** 670,676 **** return (error); } ! #define SES_FLAGS SF_NO_PRINT | SF_RETRY_SELTO | SF_RETRY_UA static int ses_runcmd(struct ses_softc *ssc, char *cdb, int cdbl, char *dptr, int *dlenp) { --- 670,677 ---- return (error); } ! #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) { *************** *** 699,705 **** 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); if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE); if (error) { --- 700,706 ---- dlen, sizeof (struct scsi_sense_data), cdbl, 60 * 1000); bcopy(cdb, ccb->csio.cdb_io.cdb_bytes, cdbl); ! 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) { *** src/sys/conf/files.orig --- src/sys/conf/files *************** *** 762,767 **** --- 762,768 ---- # 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 *** src/sys/dev/aic7xxx/aic7xxx_freebsd.h.orig --- src/sys/dev/aic7xxx/aic7xxx_freebsd.h *************** *** 37,42 **** --- 37,45 ---- #ifndef _AIC7XXX_FREEBSD_H_ #define _AIC7XXX_FREEBSD_H_ + #ifdef CAM_NEW_TRAN_CODE + #define AHC_NEW_TRAN_SETTINGS + #endif /* CAM_NEW_TRAN_CODE */ #include /* for config options */ #include /* for NPCI */ *** src/sys/kern/subr_sbuf.c.orig --- src/sys/kern/subr_sbuf.c *************** *** 29,42 **** */ #include #include #include - #include #include - #include MALLOC_DEFINE(M_SBUF, "sbuf", "string buffers"); /* * Predicates --- 29,55 ---- */ #include + #include + + #ifdef _KERNEL #include #include #include #include + #else /* _KERNEL */ + #include + #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,61 **** /* * Debugging support */ ! #ifdef INVARIANTS static void _assert_sbuf_integrity(char *fun, struct sbuf *s) { --- 68,74 ---- /* * Debugging support */ ! #if defined(_KERNEL) && defined(INVARIANTS) static void _assert_sbuf_integrity(char *fun, struct sbuf *s) { *************** *** 76,85 **** } #define assert_sbuf_integrity(s) _assert_sbuf_integrity(__FUNCTION__, (s)) #define assert_sbuf_state(s, i) _assert_sbuf_state(__FUNCTION__, (s), (i)) ! #else #define assert_sbuf_integrity(s) do { } while (0) #define assert_sbuf_state(s, i) do { } while (0) ! #endif /* * Initialize an sbuf. --- 89,98 ---- } #define assert_sbuf_integrity(s) _assert_sbuf_integrity(__FUNCTION__, (s)) #define assert_sbuf_state(s, i) _assert_sbuf_state(__FUNCTION__, (s), (i)) ! #else /* _KERNEL && INVARIANTS */ #define assert_sbuf_integrity(s) do { } while (0) #define assert_sbuf_state(s, i) do { } while (0) ! #endif /* _KERNEL && INVARIANTS */ /* * Initialize an sbuf. *************** *** 102,108 **** s->s_buf = buf; return (0); } ! s->s_buf = malloc(s->s_size, M_SBUF, M_WAITOK); if (s->s_buf == NULL) return (-1); SBUF_SETFLAG(s, SBUF_DYNAMIC); --- 115,121 ---- s->s_buf = buf; return (0); } ! s->s_buf = (char *)SBMALLOC(s->s_size); if (s->s_buf == NULL) return (-1); SBUF_SETFLAG(s, SBUF_DYNAMIC); *************** *** 147,153 **** * Append a string to an sbuf. */ int ! sbuf_cat(struct sbuf *s, char *str) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); --- 160,166 ---- * Append a string to an sbuf. */ int ! sbuf_cat(struct sbuf *s, const char *str) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); *************** *** 168,174 **** * Copy a string into an sbuf. */ int ! sbuf_cpy(struct sbuf *s, char *str) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); --- 181,187 ---- * Copy a string into an sbuf. */ int ! sbuf_cpy(struct sbuf *s, const char *str) { assert_sbuf_integrity(s); assert_sbuf_state(s, 0); *************** *** 178,192 **** } /* - * 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. */ int --- 191,196 ---- *************** *** 205,213 **** return (-1); va_start(ap, fmt); ! len = kvprintf(fmt, _sbuf_pchar, s, 10, ap); va_end(ap); KASSERT(s->s_len < s->s_size, ("wrote past end of sbuf (%d >= %d)", s->s_len, s->s_size)); --- 209,230 ---- return (-1); va_start(ap, fmt); ! 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,301 **** /* don't care if it's finished or not */ if (SBUF_ISDYNAMIC(s)) ! free(s->s_buf, M_SBUF); bzero(s, sizeof *s); } --- 313,318 ---- /* don't care if it's finished or not */ if (SBUF_ISDYNAMIC(s)) ! SBFREE(s->s_buf); bzero(s, sizeof *s); } *** /dev/null Fri Mar 23 13:41:22 2001 --- src/sys/libkern/bsearch.c Fri Mar 23 15:08:02 2001 *************** *** 0 **** --- 1,81 ---- + /* + * 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. + */ + + #if defined(LIBC_SCCS) && !defined(lint) + static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93"; + #endif /* LIBC_SCCS and not lint */ + + #include + #include + + /* + * 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); + } *** src/sys/sys/libkern.h.orig --- src/sys/sys/libkern.h *************** *** 66,71 **** --- 66,73 ---- /* 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 *** src/sys/sys/sbuf.h.orig --- src/sys/sys/sbuf.h *************** *** 46,59 **** int s_flags; /* flags */ }; /* * 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_printf(struct sbuf *s, char *fmt, ...); int sbuf_putc(struct sbuf *s, int c); int sbuf_overflowed(struct sbuf *s); --- 46,60 ---- 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, 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,65 **** --- 62,67 ---- char *sbuf_data(struct sbuf *s); int sbuf_len(struct sbuf *s); void sbuf_delete(struct sbuf *s); + __END_DECLS #endif *** src/usr.bin/kdump/mkioctls.orig --- src/usr.bin/kdump/mkioctls *************** *** 57,64 **** print "#include " print "#include " print "#include " print "#include " - print "#include " print "" print ioctl_includes print "" --- 57,64 ---- print "#include " print "#include " print "#include " + print "#include " print "#include " print "" print ioctl_includes print ""