1/*-
2 * Implementation of SCSI Direct Access Peripheral driver for CAM.
3 *
4 * Copyright (c) 1997 Justin T. Gibbs.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
--- 13 unchanged lines hidden (view full) ---
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_da.c 166861 2007-02-21 07:45:02Z n_hibma $");
31
32#include <sys/param.h>
33
34#ifdef _KERNEL
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/bio.h>
38#include <sys/sysctl.h>
39#include <sys/taskqueue.h>
40#endif /* _KERNEL */
41
42#include <sys/devicestat.h>
43#include <sys/conf.h>
44#include <sys/eventhandler.h>
45#include <sys/malloc.h>
46#include <sys/cons.h>
47
--- 8 unchanged lines hidden (view full) ---
56#include <stdio.h>
57#include <string.h>
58#endif /* _KERNEL */
59
60#include <cam/cam.h>
61#include <cam/cam_ccb.h>
62#include <cam/cam_periph.h>
63#include <cam/cam_xpt_periph.h>
64
65#include <cam/scsi/scsi_message.h>
66
67#ifndef _KERNEL
68#include <cam/scsi/scsi_da.h>
69#endif /* !_KERNEL */
70
71#ifdef _KERNEL
--- 56 unchanged lines hidden (view full) ---
128 int ordered_tag_count;
129 int outstanding_cmds;
130 struct disk_params params;
131 struct disk *disk;
132 union ccb saved_ccb;
133 struct task sysctl_task;
134 struct sysctl_ctx_list sysctl_ctx;
135 struct sysctl_oid *sysctl_tree;
136};
137
138struct da_quirk_entry {
139 struct scsi_inquiry_pattern inq_pat;
140 da_quirks quirks;
141};
142
143static const char quantum[] = "QUANTUM";
--- 402 unchanged lines hidden (view full) ---
546static struct periph_driver dadriver =
547{
548 dainit, "da",
549 TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
550};
551
552PERIPHDRIVER_DECLARE(da, dadriver);
553
554static SLIST_HEAD(,da_softc) softc_list;
555
556static int
557daopen(struct disk *dp)
558{
559 struct cam_periph *periph;
560 struct da_softc *softc;
561 int unit;
562 int error;
563 int s;
564
565 s = splsoftcam();
566 periph = (struct cam_periph *)dp->d_drv1;
567 if (periph == NULL) {
568 splx(s);
569 return (ENXIO);
570 }
571 unit = periph->unit_number;
572
573 softc = (struct da_softc *)periph->softc;
574
575 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
576 ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
577 unit));
578
579 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
580 return (error); /* error code from tsleep */
581
582 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
583 return(ENXIO);
584 softc->flags |= DA_FLAG_OPEN;
585
586 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
587 /* Invalidate our pack information. */
588 softc->flags &= ~DA_FLAG_PACK_INVALID;
589 }
590 splx(s);
591
592 error = dagetcapacity(periph);
593
594 if (error == 0) {
595
596 softc->disk->d_sectorsize = softc->params.secsize;
597 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
598 /* XXX: these are not actually "firmware" values, so they may be wrong */
--- 6 unchanged lines hidden (view full) ---
605 if (error == 0) {
606 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
607 (softc->quirks & DA_Q_NO_PREVENT) == 0)
608 daprevent(periph, PR_PREVENT);
609 } else {
610 softc->flags &= ~DA_FLAG_OPEN;
611 cam_periph_release(periph);
612 }
613 cam_periph_unlock(periph);
614 return (error);
615}
616
617static int
618daclose(struct disk *dp)
619{
620 struct cam_periph *periph;
621 struct da_softc *softc;
622 int error;
623
624 periph = (struct cam_periph *)dp->d_drv1;
625 if (periph == NULL)
626 return (ENXIO);
627
628 softc = (struct da_softc *)periph->softc;
629
630 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
631 return (error); /* error code from tsleep */
632 }
633
634 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
635 union ccb *ccb;
636
637 ccb = cam_periph_getccb(periph, /*priority*/1);
638
639 scsi_synchronize_cache(&ccb->csio,
640 /*retries*/1,
641 /*cbfcnp*/dadone,
--- 45 unchanged lines hidden (view full) ---
687 * If we've got removeable media, mark the blocksize as
688 * unavailable, since it could change when new media is
689 * inserted.
690 */
691 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
692 }
693
694 softc->flags &= ~DA_FLAG_OPEN;
695 cam_periph_unlock(periph);
696 cam_periph_release(periph);
697 return (0);
698}
699
700/*
701 * Actually translate the requested transfer into one the physical driver
702 * can understand. The transfer is described by a buf and will include
703 * only one physical transfer.
704 */
705static void
706dastrategy(struct bio *bp)
707{
708 struct cam_periph *periph;
709 struct da_softc *softc;
710 int s;
711
712 periph = (struct cam_periph *)bp->bio_disk->d_drv1;
713 if (periph == NULL) {
714 biofinish(bp, NULL, ENXIO);
715 return;
716 }
717 softc = (struct da_softc *)periph->softc;
718#if 0
719 /*
720 * check it's not too big a transfer for our adapter
721 */
722 scsi_minphys(bp,&sd_switch);
723#endif
724
725 /*
726 * Mask interrupts so that the pack cannot be invalidated until
727 * after we are in the queue. Otherwise, we might not properly
728 * clean up one of the buffers.
729 */
730 s = splbio();
731
732 /*
733 * If the device has been made invalid, error out
734 */
735 if ((softc->flags & DA_FLAG_PACK_INVALID)) {
736 splx(s);
737 biofinish(bp, NULL, ENXIO);
738 return;
739 }
740
741 /*
742 * Place it in the queue of disk activities for this disk
743 */
744 bioq_disksort(&softc->bio_queue, bp);
745
746 splx(s);
747
748 /*
749 * Schedule ourselves for performing the work.
750 */
751 xpt_schedule(periph, /* XXX priority */1);
752
753 return;
754}
755
756static int
757dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
758{
759 struct cam_periph *periph;
--- 8 unchanged lines hidden (view full) ---
768 return (ENXIO);
769 softc = (struct da_softc *)periph->softc;
770 secsize = softc->params.secsize;
771
772 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
773 return (ENXIO);
774
775 if (length > 0) {
776 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
777 csio.ccb_h.ccb_state = DA_CCB_DUMP;
778 scsi_read_write(&csio,
779 /*retries*/1,
780 dadone,
781 MSG_ORDERED_Q_TAG,
782 /*read*/FALSE,
783 /*byte2*/0,
--- 9 unchanged lines hidden (view full) ---
793 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
794 printf("Aborting dump due to I/O error.\n");
795 if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
796 CAM_SCSI_STATUS_ERROR)
797 scsi_sense_print(&csio);
798 else
799 printf("status == 0x%x, scsi status == 0x%x\n",
800 csio.ccb_h.status, csio.scsi_status);
801 return(EIO);
802 }
803 return(0);
804 }
805
806 /*
807 * Sync the disk cache contents to the physical media.
808 */
809 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
810
811 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
812 csio.ccb_h.ccb_state = DA_CCB_DUMP;
--- 22 unchanged lines hidden (view full) ---
835 } else {
836 xpt_print(periph->path, "Synchronize cache "
837 "failed, status == 0x%x, scsi status == "
838 "0x%x\n", csio.ccb_h.status,
839 csio.scsi_status);
840 }
841 }
842 }
843 return (0);
844}
845
846static void
847dainit(void)
848{
849 cam_status status;
850 struct cam_path *path;
851
852 SLIST_INIT(&softc_list);
853
854 /*
855 * Install a global async callback. This callback will
856 * receive async callbacks like "new device found".
857 */
858 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
859 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
860
861 if (status == CAM_REQ_CMP) {
--- 9 unchanged lines hidden (view full) ---
871 xpt_free_path(path);
872 }
873
874 if (status != CAM_REQ_CMP) {
875 printf("da: Failed to attach master async callback "
876 "due to status 0x%x!\n", status);
877 } else if (da_send_ordered) {
878
879 /*
880 * Schedule a periodic event to occasionally send an
881 * ordered tag to a device.
882 */
883 timeout(dasendorderedtag, NULL,
884 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
885
886 /* Register our shutdown event handler */
887 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
888 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
889 printf("dainit: shutdown event registration failed!\n");
890 }
891}
892
893static void
894daoninvalidate(struct cam_periph *periph)
895{
896 int s;
897 struct da_softc *softc;
898 struct ccb_setasync csa;
899
900 softc = (struct da_softc *)periph->softc;
901
902 /*
903 * De-register any async callbacks.
904 */
905 xpt_setup_ccb(&csa.ccb_h, periph->path,
906 /* priority */ 5);
907 csa.ccb_h.func_code = XPT_SASYNC_CB;
908 csa.event_enable = 0;
909 csa.callback = daasync;
910 csa.callback_arg = periph;
911 xpt_action((union ccb *)&csa);
912
913 softc->flags |= DA_FLAG_PACK_INVALID;
914
915 /*
916 * Although the oninvalidate() routines are always called at
917 * splsoftcam, we need to be at splbio() here to keep the buffer
918 * queue from being modified while we traverse it.
919 */
920 s = splbio();
921
922 /*
923 * Return all queued I/O with ENXIO.
924 * XXX Handle any transactions queued to the card
925 * with XPT_ABORT_CCB.
926 */
927 bioq_flush(&softc->bio_queue, NULL, ENXIO);
928 splx(s);
929
930 SLIST_REMOVE(&softc_list, softc, da_softc, links);
931
932 disk_gone(softc->disk);
933 xpt_print(periph->path, "lost device\n");
934}
935
936static void
937dacleanup(struct cam_periph *periph)
938{
939 struct da_softc *softc;
--- 4 unchanged lines hidden (view full) ---
944 /*
945 * If we can't free the sysctl tree, oh well...
946 */
947 if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
948 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
949 xpt_print(periph->path, "can't remove sysctl context\n");
950 }
951 disk_destroy(softc->disk);
952 free(softc, M_DEVBUF);
953}
954
955static void
956daasync(void *callback_arg, u_int32_t code,
957 struct cam_path *path, void *arg)
958{
959 struct cam_periph *periph;
960
961 periph = (struct cam_periph *)callback_arg;
962 switch (code) {
963 case AC_FOUND_DEVICE:
964 {
965 struct ccb_getdev *cgd;
966 cam_status status;
967
968 cgd = (struct ccb_getdev *)arg;
969 if (cgd == NULL)
970 break;
971
972 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
973 && SID_TYPE(&cgd->inq_data) != T_RBC
974 && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
975 break;
976
977 /*
978 * Allocate a peripheral instance for
979 * this device and start the probe
980 * process.
981 */
982 status = cam_periph_alloc(daregister, daoninvalidate,
983 dacleanup, dastart,
984 "da", CAM_PERIPH_BIO,
985 cgd->ccb_h.path, daasync,
986 AC_FOUND_DEVICE, cgd);
987
988 if (status != CAM_REQ_CMP
989 && status != CAM_REQ_INPROG)
990 printf("daasync: Unable to attach to new device "
991 "due to status 0x%x\n", status);
992 break;
993 }
994 case AC_SENT_BDR:
995 case AC_BUS_RESET:
996 {
997 struct da_softc *softc;
998 struct ccb_hdr *ccbh;
999 int s;
1000
1001 softc = (struct da_softc *)periph->softc;
1002 s = splsoftcam();
1003 /*
1004 * Don't fail on the expected unit attention
1005 * that will occur.
1006 */
1007 softc->flags |= DA_FLAG_RETRY_UA;
1008 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
1009 ccbh->ccb_state |= DA_CCB_RETRY_UA;
1010 splx(s);
1011 /* FALLTHROUGH*/
1012 }
1013 default:
1014 cam_periph_async(periph, code, path, arg);
1015 break;
1016 }
1017}
1018
1019static void
1020dasysctlinit(void *context, int pending)
1021{
1022 struct cam_periph *periph;
1023 struct da_softc *softc;
1024 char tmpstr[80], tmpstr2[80];
1025
1026 periph = (struct cam_periph *)context;
1027 softc = (struct da_softc *)periph->softc;
1028
1029 snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
1030 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
1031
1032 mtx_lock(&Giant);
1033 sysctl_ctx_init(&softc->sysctl_ctx);
1034 softc->flags |= DA_FLAG_SCTX_INIT;
1035 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
1036 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
1037 CTLFLAG_RD, 0, tmpstr);
1038 if (softc->sysctl_tree == NULL) {
1039 printf("dasysctlinit: unable to allocate sysctl tree\n");
1040 mtx_unlock(&Giant);
1041 return;
1042 }
1043
1044 /*
1045 * Now register the sysctl handler, so the user can the value on
1046 * the fly.
1047 */
1048 SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
1049 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
1050 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
1051 "Minimum CDB size");
1052
1053 mtx_unlock(&Giant);
1054}
1055
1056static int
1057dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
1058{
1059 int error, value;
1060
1061 value = *(int *)arg1;
--- 21 unchanged lines hidden (view full) ---
1083 *(int *)arg1 = value;
1084
1085 return (0);
1086}
1087
1088static cam_status
1089daregister(struct cam_periph *periph, void *arg)
1090{
1091 int s;
1092 struct da_softc *softc;
1093 struct ccb_setasync csa;
1094 struct ccb_pathinq cpi;
1095 struct ccb_getdev *cgd;
1096 char tmpstr[80];
1097 caddr_t match;
1098
1099 cgd = (struct ccb_getdev *)arg;
--- 73 unchanged lines hidden (view full) ---
1173 softc->minimum_cmd_size = 10;
1174 else if ((softc->minimum_cmd_size > 10)
1175 && (softc->minimum_cmd_size <= 12))
1176 softc->minimum_cmd_size = 12;
1177 else if (softc->minimum_cmd_size > 12)
1178 softc->minimum_cmd_size = 16;
1179
1180 /*
1181 * Block our timeout handler while we
1182 * add this softc to the dev list.
1183 */
1184 s = splsoftclock();
1185 SLIST_INSERT_HEAD(&softc_list, softc, links);
1186 splx(s);
1187
1188 /*
1189 * Register this media as a disk
1190 */
1191
1192 softc->disk = disk_alloc();
1193 softc->disk->d_open = daopen;
1194 softc->disk->d_close = daclose;
1195 softc->disk->d_strategy = dastrategy;
1196 softc->disk->d_dump = dadump;
1197 softc->disk->d_name = "da";
1198 softc->disk->d_drv1 = periph;
1199 softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
1200 softc->disk->d_unit = periph->unit_number;
1201 softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
1202 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
1203 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
1204 disk_create(softc->disk, DISK_VERSION);
1205
1206 /*
1207 * Add async callbacks for bus reset and
1208 * bus device reset calls. I don't bother
1209 * checking if this fails as, in most cases,
1210 * the system will function just fine without
1211 * them and the only alternative would be to
1212 * not attach the device on failure.
1213 */
1214 xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
1215 csa.ccb_h.func_code = XPT_SASYNC_CB;
1216 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
1217 csa.callback = daasync;
1218 csa.callback_arg = periph;
1219 xpt_action((union ccb *)&csa);
1220 /*
1221 * Lock this peripheral until we are setup.
1222 * This first call can't block
1223 */
1224 (void)cam_periph_lock(periph, PRIBIO);
1225 xpt_schedule(periph, /*priority*/5);
1226
1227 return(CAM_REQ_CMP);
1228}
1229
1230static void
1231dastart(struct cam_periph *periph, union ccb *start_ccb)
1232{
1233 struct da_softc *softc;
1234
1235 softc = (struct da_softc *)periph->softc;
1236
1237
1238 switch (softc->state) {
1239 case DA_STATE_NORMAL:
1240 {
1241 /* Pull a buffer from the queue and get going on it */
1242 struct bio *bp;
1243 int s;
1244
1245 /*
1246 * See if there is a buf with work for us to do..
1247 */
1248 s = splbio();
1249 bp = bioq_first(&softc->bio_queue);
1250 if (periph->immediate_priority <= periph->pinfo.priority) {
1251 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1252 ("queuing for immediate ccb\n"));
1253 start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
1254 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1255 periph_links.sle);
1256 periph->immediate_priority = CAM_PRIORITY_NONE;
1257 splx(s);
1258 wakeup(&periph->ccb_list);
1259 } else if (bp == NULL) {
1260 splx(s);
1261 xpt_release_ccb(start_ccb);
1262 } else {
1263 int oldspl;
1264 u_int8_t tag_code;
1265
1266 bioq_remove(&softc->bio_queue, bp);
1267
1268 if ((softc->flags & DA_FLAG_NEED_OTAG) != 0) {
1269 softc->flags &= ~DA_FLAG_NEED_OTAG;
1270 softc->ordered_tag_count++;
1271 tag_code = MSG_ORDERED_Q_TAG;
--- 30 unchanged lines hidden (view full) ---
1302 break;
1303 }
1304 start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
1305
1306 /*
1307 * Block out any asyncronous callbacks
1308 * while we touch the pending ccb list.
1309 */
1310 oldspl = splcam();
1311 LIST_INSERT_HEAD(&softc->pending_ccbs,
1312 &start_ccb->ccb_h, periph_links.le);
1313 softc->outstanding_cmds++;
1314 splx(oldspl);
1315
1316 /* We expect a unit attention from this device */
1317 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
1318 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
1319 softc->flags &= ~DA_FLAG_RETRY_UA;
1320 }
1321
1322 start_ccb->ccb_h.ccb_bp = bp;
1323 bp = bioq_first(&softc->bio_queue);
1324 splx(s);
1325
1326 xpt_action(start_ccb);
1327 }
1328
1329 if (bp != NULL) {
1330 /* Have more work to do, so ensure we stay scheduled */
1331 xpt_schedule(periph, /* XXX priority */1);
1332 }
--- 108 unchanged lines hidden (view full) ---
1441 struct ccb_scsiio *csio;
1442
1443 softc = (struct da_softc *)periph->softc;
1444 csio = &done_ccb->csio;
1445 switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
1446 case DA_CCB_BUFFER_IO:
1447 {
1448 struct bio *bp;
1449 int oldspl;
1450
1451 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
1452 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1453 int error;
1454 int s;
1455 int sf;
1456
1457 if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
1458 sf = SF_RETRY_UA;
1459 else
1460 sf = 0;
1461
1462 error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
1463 if (error == ERESTART) {
1464 /*
1465 * A retry was scheuled, so
1466 * just return.
1467 */
1468 return;
1469 }
1470 if (error != 0) {
1471
1472 s = splbio();
1473
1474 if (error == ENXIO) {
1475 /*
1476 * Catastrophic error. Mark our pack as
1477 * invalid.
1478 */
1479 /*
1480 * XXX See if this is really a media
1481 * XXX change first?
--- 4 unchanged lines hidden (view full) ---
1486 }
1487
1488 /*
1489 * return all queued I/O with EIO, so that
1490 * the client can retry these I/Os in the
1491 * proper order should it attempt to recover.
1492 */
1493 bioq_flush(&softc->bio_queue, NULL, EIO);
1494 splx(s);
1495 bp->bio_error = error;
1496 bp->bio_resid = bp->bio_bcount;
1497 bp->bio_flags |= BIO_ERROR;
1498 } else {
1499 bp->bio_resid = csio->resid;
1500 bp->bio_error = 0;
1501 if (bp->bio_resid != 0)
1502 bp->bio_flags |= BIO_ERROR;
--- 11 unchanged lines hidden (view full) ---
1514 if (csio->resid > 0)
1515 bp->bio_flags |= BIO_ERROR;
1516 }
1517
1518 /*
1519 * Block out any asyncronous callbacks
1520 * while we touch the pending ccb list.
1521 */
1522 oldspl = splcam();
1523 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1524 softc->outstanding_cmds--;
1525 if (softc->outstanding_cmds == 0)
1526 softc->flags |= DA_FLAG_WENT_IDLE;
1527 splx(oldspl);
1528
1529 biodone(bp);
1530 break;
1531 }
1532 case DA_CCB_PROBE:
1533 case DA_CCB_PROBE2:
1534 {
1535 struct scsi_read_capacity_data *rdcap;
--- 169 unchanged lines hidden (view full) ---
1705 * Since our peripheral may be invalidated by an error
1706 * above or an external event, we must release our CCB
1707 * before releasing the probe lock on the peripheral.
1708 * The peripheral will only go away once the last lock
1709 * is removed, and we need it around for the CCB release
1710 * operation.
1711 */
1712 xpt_release_ccb(done_ccb);
1713 cam_periph_unlock(periph);
1714 return;
1715 }
1716 case DA_CCB_WAITING:
1717 {
1718 /* Caller will release the CCB */
1719 wakeup(&done_ccb->ccb_h.cbfcnp);
1720 return;
1721 }
--- 106 unchanged lines hidden (view full) ---
1828 error = 0;
1829 sense_flags = SF_RETRY_UA;
1830 if (softc->flags & DA_FLAG_PACK_REMOVABLE)
1831 sense_flags |= SF_NO_PRINT;
1832
1833 /* Do a read capacity */
1834 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
1835 M_TEMP,
1836 M_WAITOK);
1837
1838 ccb = cam_periph_getccb(periph, /*priority*/1);
1839 scsi_read_capacity(&ccb->csio,
1840 /*retries*/4,
1841 /*cbfncp*/dadone,
1842 MSG_SIMPLE_Q_TAG,
1843 rcap,
1844 SSD_FULL_SIZE,
--- 109 unchanged lines hidden (view full) ---
1954 dp->secs_per_track = ccg.secs_per_track;
1955 dp->cylinders = ccg.cylinders;
1956 }
1957}
1958
1959static void
1960dasendorderedtag(void *arg)
1961{
1962 struct da_softc *softc;
1963 int s;
1964 if (da_send_ordered) {
1965 for (softc = SLIST_FIRST(&softc_list);
1966 softc != NULL;
1967 softc = SLIST_NEXT(softc, links)) {
1968 s = splsoftcam();
1969 if ((softc->ordered_tag_count == 0)
1970 && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
1971 softc->flags |= DA_FLAG_NEED_OTAG;
1972 }
1973 if (softc->outstanding_cmds > 0)
1974 softc->flags &= ~DA_FLAG_WENT_IDLE;
1975
1976 softc->ordered_tag_count = 0;
1977 splx(s);
1978 }
1979 /* Queue us up again */
1980 timeout(dasendorderedtag, NULL,
1981 (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
1982 }
1983}
1984
1985/*
1986 * Step through all DA peripheral drivers, and if the device is still open,
1987 * sync the disk cache to physical media.
1988 */
1989static void
1990dashutdown(void * arg, int howto)
--- 94 unchanged lines hidden ---
2 * Implementation of SCSI Direct Access Peripheral driver for CAM.
3 *
4 * Copyright (c) 1997 Justin T. Gibbs.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
--- 13 unchanged lines hidden (view full) ---
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_da.c 166861 2007-02-21 07:45:02Z n_hibma $");
31
32#include <sys/param.h>
33
34#ifdef _KERNEL
35#include <sys/systm.h>
36#include <sys/kernel.h>
37#include <sys/bio.h>
38#include <sys/sysctl.h>
39#include <sys/taskqueue.h>
40#endif /* _KERNEL */
41
42#include <sys/devicestat.h>
43#include <sys/conf.h>
44#include <sys/eventhandler.h>
45#include <sys/malloc.h>
46#include <sys/cons.h>
47
--- 8 unchanged lines hidden (view full) ---
56#include <stdio.h>
57#include <string.h>
58#endif /* _KERNEL */
59
60#include <cam/cam.h>
61#include <cam/cam_ccb.h>
62#include <cam/cam_periph.h>
63#include <cam/cam_xpt_periph.h>
64
65#include <cam/scsi/scsi_message.h>
66
67#ifndef _KERNEL
68#include <cam/scsi/scsi_da.h>
69#endif /* !_KERNEL */
70
71#ifdef _KERNEL
--- 56 unchanged lines hidden (view full) ---
128 int ordered_tag_count;
129 int outstanding_cmds;
130 struct disk_params params;
131 struct disk *disk;
132 union ccb saved_ccb;
133 struct task sysctl_task;
134 struct sysctl_ctx_list sysctl_ctx;
135 struct sysctl_oid *sysctl_tree;
136};
137
138struct da_quirk_entry {
139 struct scsi_inquiry_pattern inq_pat;
140 da_quirks quirks;
141};
142
143static const char quantum[] = "QUANTUM";
--- 402 unchanged lines hidden (view full) ---
546static struct periph_driver dadriver =
547{
548 dainit, "da",
549 TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
550};
551
552PERIPHDRIVER_DECLARE(da, dadriver);
553
554static SLIST_HEAD(,da_softc) softc_list;
555
556static int
557daopen(struct disk *dp)
558{
559 struct cam_periph *periph;
560 struct da_softc *softc;
561 int unit;
562 int error;
563 int s;
564
565 s = splsoftcam();
566 periph = (struct cam_periph *)dp->d_drv1;
567 if (periph == NULL) {
568 splx(s);
569 return (ENXIO);
570 }
571 unit = periph->unit_number;
572
573 softc = (struct da_softc *)periph->softc;
574
575 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
576 ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
577 unit));
578
579 if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0)
580 return (error); /* error code from tsleep */
581
582 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
583 return(ENXIO);
584 softc->flags |= DA_FLAG_OPEN;
585
586 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
587 /* Invalidate our pack information. */
588 softc->flags &= ~DA_FLAG_PACK_INVALID;
589 }
590 splx(s);
591
592 error = dagetcapacity(periph);
593
594 if (error == 0) {
595
596 softc->disk->d_sectorsize = softc->params.secsize;
597 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
598 /* XXX: these are not actually "firmware" values, so they may be wrong */
--- 6 unchanged lines hidden (view full) ---
605 if (error == 0) {
606 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
607 (softc->quirks & DA_Q_NO_PREVENT) == 0)
608 daprevent(periph, PR_PREVENT);
609 } else {
610 softc->flags &= ~DA_FLAG_OPEN;
611 cam_periph_release(periph);
612 }
613 cam_periph_unlock(periph);
614 return (error);
615}
616
617static int
618daclose(struct disk *dp)
619{
620 struct cam_periph *periph;
621 struct da_softc *softc;
622 int error;
623
624 periph = (struct cam_periph *)dp->d_drv1;
625 if (periph == NULL)
626 return (ENXIO);
627
628 softc = (struct da_softc *)periph->softc;
629
630 if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
631 return (error); /* error code from tsleep */
632 }
633
634 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
635 union ccb *ccb;
636
637 ccb = cam_periph_getccb(periph, /*priority*/1);
638
639 scsi_synchronize_cache(&ccb->csio,
640 /*retries*/1,
641 /*cbfcnp*/dadone,
--- 45 unchanged lines hidden (view full) ---
687 * If we've got removeable media, mark the blocksize as
688 * unavailable, since it could change when new media is
689 * inserted.
690 */
691 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
692 }
693
694 softc->flags &= ~DA_FLAG_OPEN;
695 cam_periph_unlock(periph);
696 cam_periph_release(periph);
697 return (0);
698}
699
700/*
701 * Actually translate the requested transfer into one the physical driver
702 * can understand. The transfer is described by a buf and will include
703 * only one physical transfer.
704 */
705static void
706dastrategy(struct bio *bp)
707{
708 struct cam_periph *periph;
709 struct da_softc *softc;
710 int s;
711
712 periph = (struct cam_periph *)bp->bio_disk->d_drv1;
713 if (periph == NULL) {
714 biofinish(bp, NULL, ENXIO);
715 return;
716 }
717 softc = (struct da_softc *)periph->softc;
718#if 0
719 /*
720 * check it's not too big a transfer for our adapter
721 */
722 scsi_minphys(bp,&sd_switch);
723#endif
724
725 /*
726 * Mask interrupts so that the pack cannot be invalidated until
727 * after we are in the queue. Otherwise, we might not properly
728 * clean up one of the buffers.
729 */
730 s = splbio();
731
732 /*
733 * If the device has been made invalid, error out
734 */
735 if ((softc->flags & DA_FLAG_PACK_INVALID)) {
736 splx(s);
737 biofinish(bp, NULL, ENXIO);
738 return;
739 }
740
741 /*
742 * Place it in the queue of disk activities for this disk
743 */
744 bioq_disksort(&softc->bio_queue, bp);
745
746 splx(s);
747
748 /*
749 * Schedule ourselves for performing the work.
750 */
751 xpt_schedule(periph, /* XXX priority */1);
752
753 return;
754}
755
756static int
757dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
758{
759 struct cam_periph *periph;
--- 8 unchanged lines hidden (view full) ---
768 return (ENXIO);
769 softc = (struct da_softc *)periph->softc;
770 secsize = softc->params.secsize;
771
772 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
773 return (ENXIO);
774
775 if (length > 0) {
776 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
777 csio.ccb_h.ccb_state = DA_CCB_DUMP;
778 scsi_read_write(&csio,
779 /*retries*/1,
780 dadone,
781 MSG_ORDERED_Q_TAG,
782 /*read*/FALSE,
783 /*byte2*/0,
--- 9 unchanged lines hidden (view full) ---
793 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
794 printf("Aborting dump due to I/O error.\n");
795 if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
796 CAM_SCSI_STATUS_ERROR)
797 scsi_sense_print(&csio);
798 else
799 printf("status == 0x%x, scsi status == 0x%x\n",
800 csio.ccb_h.status, csio.scsi_status);
801 return(EIO);
802 }
803 return(0);
804 }
805
806 /*
807 * Sync the disk cache contents to the physical media.
808 */
809 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
810
811 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
812 csio.ccb_h.ccb_state = DA_CCB_DUMP;
--- 22 unchanged lines hidden (view full) ---
835 } else {
836 xpt_print(periph->path, "Synchronize cache "
837 "failed, status == 0x%x, scsi status == "
838 "0x%x\n", csio.ccb_h.status,
839 csio.scsi_status);
840 }
841 }
842 }
843 return (0);
844}
845
846static void
847dainit(void)
848{
849 cam_status status;
850 struct cam_path *path;
851
852 SLIST_INIT(&softc_list);
853
854 /*
855 * Install a global async callback. This callback will
856 * receive async callbacks like "new device found".
857 */
858 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
859 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
860
861 if (status == CAM_REQ_CMP) {
--- 9 unchanged lines hidden (view full) ---
871 xpt_free_path(path);
872 }
873
874 if (status != CAM_REQ_CMP) {
875 printf("da: Failed to attach master async callback "
876 "due to status 0x%x!\n", status);
877 } else if (da_send_ordered) {
878
879 /*
880 * Schedule a periodic event to occasionally send an
881 * ordered tag to a device.
882 */
883 timeout(dasendorderedtag, NULL,
884 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL);
885
886 /* Register our shutdown event handler */
887 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
888 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
889 printf("dainit: shutdown event registration failed!\n");
890 }
891}
892
893static void
894daoninvalidate(struct cam_periph *periph)
895{
896 int s;
897 struct da_softc *softc;
898 struct ccb_setasync csa;
899
900 softc = (struct da_softc *)periph->softc;
901
902 /*
903 * De-register any async callbacks.
904 */
905 xpt_setup_ccb(&csa.ccb_h, periph->path,
906 /* priority */ 5);
907 csa.ccb_h.func_code = XPT_SASYNC_CB;
908 csa.event_enable = 0;
909 csa.callback = daasync;
910 csa.callback_arg = periph;
911 xpt_action((union ccb *)&csa);
912
913 softc->flags |= DA_FLAG_PACK_INVALID;
914
915 /*
916 * Although the oninvalidate() routines are always called at
917 * splsoftcam, we need to be at splbio() here to keep the buffer
918 * queue from being modified while we traverse it.
919 */
920 s = splbio();
921
922 /*
923 * Return all queued I/O with ENXIO.
924 * XXX Handle any transactions queued to the card
925 * with XPT_ABORT_CCB.
926 */
927 bioq_flush(&softc->bio_queue, NULL, ENXIO);
928 splx(s);
929
930 SLIST_REMOVE(&softc_list, softc, da_softc, links);
931
932 disk_gone(softc->disk);
933 xpt_print(periph->path, "lost device\n");
934}
935
936static void
937dacleanup(struct cam_periph *periph)
938{
939 struct da_softc *softc;
--- 4 unchanged lines hidden (view full) ---
944 /*
945 * If we can't free the sysctl tree, oh well...
946 */
947 if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
948 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
949 xpt_print(periph->path, "can't remove sysctl context\n");
950 }
951 disk_destroy(softc->disk);
952 free(softc, M_DEVBUF);
953}
954
955static void
956daasync(void *callback_arg, u_int32_t code,
957 struct cam_path *path, void *arg)
958{
959 struct cam_periph *periph;
960
961 periph = (struct cam_periph *)callback_arg;
962 switch (code) {
963 case AC_FOUND_DEVICE:
964 {
965 struct ccb_getdev *cgd;
966 cam_status status;
967
968 cgd = (struct ccb_getdev *)arg;
969 if (cgd == NULL)
970 break;
971
972 if (SID_TYPE(&cgd->inq_data) != T_DIRECT
973 && SID_TYPE(&cgd->inq_data) != T_RBC
974 && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
975 break;
976
977 /*
978 * Allocate a peripheral instance for
979 * this device and start the probe
980 * process.
981 */
982 status = cam_periph_alloc(daregister, daoninvalidate,
983 dacleanup, dastart,
984 "da", CAM_PERIPH_BIO,
985 cgd->ccb_h.path, daasync,
986 AC_FOUND_DEVICE, cgd);
987
988 if (status != CAM_REQ_CMP
989 && status != CAM_REQ_INPROG)
990 printf("daasync: Unable to attach to new device "
991 "due to status 0x%x\n", status);
992 break;
993 }
994 case AC_SENT_BDR:
995 case AC_BUS_RESET:
996 {
997 struct da_softc *softc;
998 struct ccb_hdr *ccbh;
999 int s;
1000
1001 softc = (struct da_softc *)periph->softc;
1002 s = splsoftcam();
1003 /*
1004 * Don't fail on the expected unit attention
1005 * that will occur.
1006 */
1007 softc->flags |= DA_FLAG_RETRY_UA;
1008 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
1009 ccbh->ccb_state |= DA_CCB_RETRY_UA;
1010 splx(s);
1011 /* FALLTHROUGH*/
1012 }
1013 default:
1014 cam_periph_async(periph, code, path, arg);
1015 break;
1016 }
1017}
1018
1019static void
1020dasysctlinit(void *context, int pending)
1021{
1022 struct cam_periph *periph;
1023 struct da_softc *softc;
1024 char tmpstr[80], tmpstr2[80];
1025
1026 periph = (struct cam_periph *)context;
1027 softc = (struct da_softc *)periph->softc;
1028
1029 snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
1030 snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
1031
1032 mtx_lock(&Giant);
1033 sysctl_ctx_init(&softc->sysctl_ctx);
1034 softc->flags |= DA_FLAG_SCTX_INIT;
1035 softc->sysctl_tree = SYSCTL_ADD_NODE(&softc->sysctl_ctx,
1036 SYSCTL_STATIC_CHILDREN(_kern_cam_da), OID_AUTO, tmpstr2,
1037 CTLFLAG_RD, 0, tmpstr);
1038 if (softc->sysctl_tree == NULL) {
1039 printf("dasysctlinit: unable to allocate sysctl tree\n");
1040 mtx_unlock(&Giant);
1041 return;
1042 }
1043
1044 /*
1045 * Now register the sysctl handler, so the user can the value on
1046 * the fly.
1047 */
1048 SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
1049 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
1050 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
1051 "Minimum CDB size");
1052
1053 mtx_unlock(&Giant);
1054}
1055
1056static int
1057dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
1058{
1059 int error, value;
1060
1061 value = *(int *)arg1;
--- 21 unchanged lines hidden (view full) ---
1083 *(int *)arg1 = value;
1084
1085 return (0);
1086}
1087
1088static cam_status
1089daregister(struct cam_periph *periph, void *arg)
1090{
1091 int s;
1092 struct da_softc *softc;
1093 struct ccb_setasync csa;
1094 struct ccb_pathinq cpi;
1095 struct ccb_getdev *cgd;
1096 char tmpstr[80];
1097 caddr_t match;
1098
1099 cgd = (struct ccb_getdev *)arg;
--- 73 unchanged lines hidden (view full) ---
1173 softc->minimum_cmd_size = 10;
1174 else if ((softc->minimum_cmd_size > 10)
1175 && (softc->minimum_cmd_size <= 12))
1176 softc->minimum_cmd_size = 12;
1177 else if (softc->minimum_cmd_size > 12)
1178 softc->minimum_cmd_size = 16;
1179
1180 /*
1181 * Block our timeout handler while we
1182 * add this softc to the dev list.
1183 */
1184 s = splsoftclock();
1185 SLIST_INSERT_HEAD(&softc_list, softc, links);
1186 splx(s);
1187
1188 /*
1189 * Register this media as a disk
1190 */
1191
1192 softc->disk = disk_alloc();
1193 softc->disk->d_open = daopen;
1194 softc->disk->d_close = daclose;
1195 softc->disk->d_strategy = dastrategy;
1196 softc->disk->d_dump = dadump;
1197 softc->disk->d_name = "da";
1198 softc->disk->d_drv1 = periph;
1199 softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
1200 softc->disk->d_unit = periph->unit_number;
1201 softc->disk->d_flags = DISKFLAG_NEEDSGIANT;
1202 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
1203 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
1204 disk_create(softc->disk, DISK_VERSION);
1205
1206 /*
1207 * Add async callbacks for bus reset and
1208 * bus device reset calls. I don't bother
1209 * checking if this fails as, in most cases,
1210 * the system will function just fine without
1211 * them and the only alternative would be to
1212 * not attach the device on failure.
1213 */
1214 xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
1215 csa.ccb_h.func_code = XPT_SASYNC_CB;
1216 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
1217 csa.callback = daasync;
1218 csa.callback_arg = periph;
1219 xpt_action((union ccb *)&csa);
1220 /*
1221 * Lock this peripheral until we are setup.
1222 * This first call can't block
1223 */
1224 (void)cam_periph_lock(periph, PRIBIO);
1225 xpt_schedule(periph, /*priority*/5);
1226
1227 return(CAM_REQ_CMP);
1228}
1229
1230static void
1231dastart(struct cam_periph *periph, union ccb *start_ccb)
1232{
1233 struct da_softc *softc;
1234
1235 softc = (struct da_softc *)periph->softc;
1236
1237
1238 switch (softc->state) {
1239 case DA_STATE_NORMAL:
1240 {
1241 /* Pull a buffer from the queue and get going on it */
1242 struct bio *bp;
1243 int s;
1244
1245 /*
1246 * See if there is a buf with work for us to do..
1247 */
1248 s = splbio();
1249 bp = bioq_first(&softc->bio_queue);
1250 if (periph->immediate_priority <= periph->pinfo.priority) {
1251 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1252 ("queuing for immediate ccb\n"));
1253 start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
1254 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1255 periph_links.sle);
1256 periph->immediate_priority = CAM_PRIORITY_NONE;
1257 splx(s);
1258 wakeup(&periph->ccb_list);
1259 } else if (bp == NULL) {
1260 splx(s);
1261 xpt_release_ccb(start_ccb);
1262 } else {
1263 int oldspl;
1264 u_int8_t tag_code;
1265
1266 bioq_remove(&softc->bio_queue, bp);
1267
1268 if ((softc->flags & DA_FLAG_NEED_OTAG) != 0) {
1269 softc->flags &= ~DA_FLAG_NEED_OTAG;
1270 softc->ordered_tag_count++;
1271 tag_code = MSG_ORDERED_Q_TAG;
--- 30 unchanged lines hidden (view full) ---
1302 break;
1303 }
1304 start_ccb->ccb_h.ccb_state = DA_CCB_BUFFER_IO;
1305
1306 /*
1307 * Block out any asyncronous callbacks
1308 * while we touch the pending ccb list.
1309 */
1310 oldspl = splcam();
1311 LIST_INSERT_HEAD(&softc->pending_ccbs,
1312 &start_ccb->ccb_h, periph_links.le);
1313 softc->outstanding_cmds++;
1314 splx(oldspl);
1315
1316 /* We expect a unit attention from this device */
1317 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
1318 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
1319 softc->flags &= ~DA_FLAG_RETRY_UA;
1320 }
1321
1322 start_ccb->ccb_h.ccb_bp = bp;
1323 bp = bioq_first(&softc->bio_queue);
1324 splx(s);
1325
1326 xpt_action(start_ccb);
1327 }
1328
1329 if (bp != NULL) {
1330 /* Have more work to do, so ensure we stay scheduled */
1331 xpt_schedule(periph, /* XXX priority */1);
1332 }
--- 108 unchanged lines hidden (view full) ---
1441 struct ccb_scsiio *csio;
1442
1443 softc = (struct da_softc *)periph->softc;
1444 csio = &done_ccb->csio;
1445 switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
1446 case DA_CCB_BUFFER_IO:
1447 {
1448 struct bio *bp;
1449 int oldspl;
1450
1451 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
1452 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1453 int error;
1454 int s;
1455 int sf;
1456
1457 if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
1458 sf = SF_RETRY_UA;
1459 else
1460 sf = 0;
1461
1462 error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
1463 if (error == ERESTART) {
1464 /*
1465 * A retry was scheuled, so
1466 * just return.
1467 */
1468 return;
1469 }
1470 if (error != 0) {
1471
1472 s = splbio();
1473
1474 if (error == ENXIO) {
1475 /*
1476 * Catastrophic error. Mark our pack as
1477 * invalid.
1478 */
1479 /*
1480 * XXX See if this is really a media
1481 * XXX change first?
--- 4 unchanged lines hidden (view full) ---
1486 }
1487
1488 /*
1489 * return all queued I/O with EIO, so that
1490 * the client can retry these I/Os in the
1491 * proper order should it attempt to recover.
1492 */
1493 bioq_flush(&softc->bio_queue, NULL, EIO);
1494 splx(s);
1495 bp->bio_error = error;
1496 bp->bio_resid = bp->bio_bcount;
1497 bp->bio_flags |= BIO_ERROR;
1498 } else {
1499 bp->bio_resid = csio->resid;
1500 bp->bio_error = 0;
1501 if (bp->bio_resid != 0)
1502 bp->bio_flags |= BIO_ERROR;
--- 11 unchanged lines hidden (view full) ---
1514 if (csio->resid > 0)
1515 bp->bio_flags |= BIO_ERROR;
1516 }
1517
1518 /*
1519 * Block out any asyncronous callbacks
1520 * while we touch the pending ccb list.
1521 */
1522 oldspl = splcam();
1523 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1524 softc->outstanding_cmds--;
1525 if (softc->outstanding_cmds == 0)
1526 softc->flags |= DA_FLAG_WENT_IDLE;
1527 splx(oldspl);
1528
1529 biodone(bp);
1530 break;
1531 }
1532 case DA_CCB_PROBE:
1533 case DA_CCB_PROBE2:
1534 {
1535 struct scsi_read_capacity_data *rdcap;
--- 169 unchanged lines hidden (view full) ---
1705 * Since our peripheral may be invalidated by an error
1706 * above or an external event, we must release our CCB
1707 * before releasing the probe lock on the peripheral.
1708 * The peripheral will only go away once the last lock
1709 * is removed, and we need it around for the CCB release
1710 * operation.
1711 */
1712 xpt_release_ccb(done_ccb);
1713 cam_periph_unlock(periph);
1714 return;
1715 }
1716 case DA_CCB_WAITING:
1717 {
1718 /* Caller will release the CCB */
1719 wakeup(&done_ccb->ccb_h.cbfcnp);
1720 return;
1721 }
--- 106 unchanged lines hidden (view full) ---
1828 error = 0;
1829 sense_flags = SF_RETRY_UA;
1830 if (softc->flags & DA_FLAG_PACK_REMOVABLE)
1831 sense_flags |= SF_NO_PRINT;
1832
1833 /* Do a read capacity */
1834 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
1835 M_TEMP,
1836 M_WAITOK);
1837
1838 ccb = cam_periph_getccb(periph, /*priority*/1);
1839 scsi_read_capacity(&ccb->csio,
1840 /*retries*/4,
1841 /*cbfncp*/dadone,
1842 MSG_SIMPLE_Q_TAG,
1843 rcap,
1844 SSD_FULL_SIZE,
--- 109 unchanged lines hidden (view full) ---
1954 dp->secs_per_track = ccg.secs_per_track;
1955 dp->cylinders = ccg.cylinders;
1956 }
1957}
1958
1959static void
1960dasendorderedtag(void *arg)
1961{
1962 struct da_softc *softc;
1963 int s;
1964 if (da_send_ordered) {
1965 for (softc = SLIST_FIRST(&softc_list);
1966 softc != NULL;
1967 softc = SLIST_NEXT(softc, links)) {
1968 s = splsoftcam();
1969 if ((softc->ordered_tag_count == 0)
1970 && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
1971 softc->flags |= DA_FLAG_NEED_OTAG;
1972 }
1973 if (softc->outstanding_cmds > 0)
1974 softc->flags &= ~DA_FLAG_WENT_IDLE;
1975
1976 softc->ordered_tag_count = 0;
1977 splx(s);
1978 }
1979 /* Queue us up again */
1980 timeout(dasendorderedtag, NULL,
1981 (da_default_timeout * hz) / DA_ORDEREDTAG_INTERVAL);
1982 }
1983}
1984
1985/*
1986 * Step through all DA peripheral drivers, and if the device is still open,
1987 * sync the disk cache to physical media.
1988 */
1989static void
1990dashutdown(void * arg, int howto)
--- 94 unchanged lines hidden ---