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 168752 2007-04-15 08:49:19Z scottl $");
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#include <sys/lock.h>
41#include <sys/mutex.h>
42#endif /* _KERNEL */
43
44#include <sys/devicestat.h>
45#include <sys/conf.h>
46#include <sys/eventhandler.h>
47#include <sys/malloc.h>
48#include <sys/cons.h>
49
--- 8 unchanged lines hidden (view full) ---
58#include <stdio.h>
59#include <string.h>
60#endif /* _KERNEL */
61
62#include <cam/cam.h>
63#include <cam/cam_ccb.h>
64#include <cam/cam_periph.h>
65#include <cam/cam_xpt_periph.h>
66#include <cam/cam_sim.h>
67
68#include <cam/scsi/scsi_message.h>
69
70#ifndef _KERNEL
71#include <cam/scsi/scsi_da.h>
72#endif /* !_KERNEL */
73
74#ifdef _KERNEL
--- 56 unchanged lines hidden (view full) ---
131 int ordered_tag_count;
132 int outstanding_cmds;
133 struct disk_params params;
134 struct disk *disk;
135 union ccb saved_ccb;
136 struct task sysctl_task;
137 struct sysctl_ctx_list sysctl_ctx;
138 struct sysctl_oid *sysctl_tree;
139 struct callout sendordered_c;
140};
141
142struct da_quirk_entry {
143 struct scsi_inquiry_pattern inq_pat;
144 da_quirks quirks;
145};
146
147static const char quantum[] = "QUANTUM";
--- 402 unchanged lines hidden (view full) ---
550static struct periph_driver dadriver =
551{
552 dainit, "da",
553 TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
554};
555
556PERIPHDRIVER_DECLARE(da, dadriver);
557
558static int
559daopen(struct disk *dp)
560{
561 struct cam_periph *periph;
562 struct da_softc *softc;
563 int unit;
564 int error;
565
566 periph = (struct cam_periph *)dp->d_drv1;
567 if (periph == NULL) {
568 return (ENXIO);
569 }
570
571 if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
572 return(ENXIO);
573 }
574
575 cam_periph_lock(periph);
576 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
577 cam_periph_unlock(periph);
578 cam_periph_release(periph);
579 return (error);
580 }
581
582 unit = periph->unit_number;
583 softc = (struct da_softc *)periph->softc;
584 softc->flags |= DA_FLAG_OPEN;
585
586 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
587 ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
588 unit));
589
590 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
591 /* Invalidate our pack information. */
592 softc->flags &= ~DA_FLAG_PACK_INVALID;
593 }
594
595 error = dagetcapacity(periph);
596
597 if (error == 0) {
598
599 softc->disk->d_sectorsize = softc->params.secsize;
600 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
601 /* XXX: these are not actually "firmware" values, so they may be wrong */
--- 6 unchanged lines hidden (view full) ---
608 if (error == 0) {
609 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
610 (softc->quirks & DA_Q_NO_PREVENT) == 0)
611 daprevent(periph, PR_PREVENT);
612 } else {
613 softc->flags &= ~DA_FLAG_OPEN;
614 cam_periph_release(periph);
615 }
616 cam_periph_unhold(periph);
617 cam_periph_unlock(periph);
618 return (error);
619}
620
621static int
622daclose(struct disk *dp)
623{
624 struct cam_periph *periph;
625 struct da_softc *softc;
626 int error;
627
628 periph = (struct cam_periph *)dp->d_drv1;
629 if (periph == NULL)
630 return (ENXIO);
631
632 cam_periph_lock(periph);
633 if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
634 cam_periph_unlock(periph);
635 cam_periph_release(periph);
636 return (error);
637 }
638
639 softc = (struct da_softc *)periph->softc;
640
641 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
642 union ccb *ccb;
643
644 ccb = cam_periph_getccb(periph, /*priority*/1);
645
646 scsi_synchronize_cache(&ccb->csio,
647 /*retries*/1,
648 /*cbfcnp*/dadone,
--- 45 unchanged lines hidden (view full) ---
694 * If we've got removeable media, mark the blocksize as
695 * unavailable, since it could change when new media is
696 * inserted.
697 */
698 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
699 }
700
701 softc->flags &= ~DA_FLAG_OPEN;
702 cam_periph_unhold(periph);
703 cam_periph_unlock(periph);
704 cam_periph_release(periph);
705 return (0);
706}
707
708/*
709 * Actually translate the requested transfer into one the physical driver
710 * can understand. The transfer is described by a buf and will include
711 * only one physical transfer.
712 */
713static void
714dastrategy(struct bio *bp)
715{
716 struct cam_periph *periph;
717 struct da_softc *softc;
718
719 periph = (struct cam_periph *)bp->bio_disk->d_drv1;
720 if (periph == NULL) {
721 biofinish(bp, NULL, ENXIO);
722 return;
723 }
724 softc = (struct da_softc *)periph->softc;
725
726 cam_periph_lock(periph);
727
728#if 0
729 /*
730 * check it's not too big a transfer for our adapter
731 */
732 scsi_minphys(bp,&sd_switch);
733#endif
734
735 /*
736 * Mask interrupts so that the pack cannot be invalidated until
737 * after we are in the queue. Otherwise, we might not properly
738 * clean up one of the buffers.
739 */
740
741 /*
742 * If the device has been made invalid, error out
743 */
744 if ((softc->flags & DA_FLAG_PACK_INVALID)) {
745 cam_periph_unlock(periph);
746 biofinish(bp, NULL, ENXIO);
747 return;
748 }
749
750 /*
751 * Place it in the queue of disk activities for this disk
752 */
753 bioq_disksort(&softc->bio_queue, bp);
754
755 /*
756 * Schedule ourselves for performing the work.
757 */
758 xpt_schedule(periph, /* XXX priority */1);
759 cam_periph_unlock(periph);
760
761 return;
762}
763
764static int
765dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
766{
767 struct cam_periph *periph;
--- 8 unchanged lines hidden (view full) ---
776 return (ENXIO);
777 softc = (struct da_softc *)periph->softc;
778 secsize = softc->params.secsize;
779
780 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
781 return (ENXIO);
782
783 if (length > 0) {
784 periph->flags |= CAM_PERIPH_POLLED;
785 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
786 csio.ccb_h.ccb_state = DA_CCB_DUMP;
787 scsi_read_write(&csio,
788 /*retries*/1,
789 dadone,
790 MSG_ORDERED_Q_TAG,
791 /*read*/FALSE,
792 /*byte2*/0,
--- 9 unchanged lines hidden (view full) ---
802 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
803 printf("Aborting dump due to I/O error.\n");
804 if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
805 CAM_SCSI_STATUS_ERROR)
806 scsi_sense_print(&csio);
807 else
808 printf("status == 0x%x, scsi status == 0x%x\n",
809 csio.ccb_h.status, csio.scsi_status);
810 periph->flags |= CAM_PERIPH_POLLED;
811 return(EIO);
812 }
813 return(0);
814 }
815
816 /*
817 * Sync the disk cache contents to the physical media.
818 */
819 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
820
821 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
822 csio.ccb_h.ccb_state = DA_CCB_DUMP;
--- 22 unchanged lines hidden (view full) ---
845 } else {
846 xpt_print(periph->path, "Synchronize cache "
847 "failed, status == 0x%x, scsi status == "
848 "0x%x\n", csio.ccb_h.status,
849 csio.scsi_status);
850 }
851 }
852 }
853 periph->flags &= ~CAM_PERIPH_POLLED;
854 return (0);
855}
856
857static void
858dainit(void)
859{
860 cam_status status;
861 struct cam_path *path;
862
863 /*
864 * Install a global async callback. This callback will
865 * receive async callbacks like "new device found".
866 */
867 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
868 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
869
870 if (status == CAM_REQ_CMP) {
--- 9 unchanged lines hidden (view full) ---
880 xpt_free_path(path);
881 }
882
883 if (status != CAM_REQ_CMP) {
884 printf("da: Failed to attach master async callback "
885 "due to status 0x%x!\n", status);
886 } else if (da_send_ordered) {
887
888 /* Register our shutdown event handler */
889 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
890 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
891 printf("dainit: shutdown event registration failed!\n");
892 }
893}
894
895static void
896daoninvalidate(struct cam_periph *periph)
897{
898 struct da_softc *softc;
899 struct ccb_setasync csa;
900
901 softc = (struct da_softc *)periph->softc;
902
903 /*
904 * De-register any async callbacks.
905 */
906 xpt_setup_ccb(&csa.ccb_h, periph->path,
907 /* priority */ 5);
908 csa.ccb_h.func_code = XPT_SASYNC_CB;
909 csa.event_enable = 0;
910 csa.callback = daasync;
911 csa.callback_arg = periph;
912 xpt_action((union ccb *)&csa);
913
914 softc->flags |= DA_FLAG_PACK_INVALID;
915
916 /*
917 * Return all queued I/O with ENXIO.
918 * XXX Handle any transactions queued to the card
919 * with XPT_ABORT_CCB.
920 */
921 bioq_flush(&softc->bio_queue, NULL, ENXIO);
922
923 disk_gone(softc->disk);
924 xpt_print(periph->path, "lost device\n");
925}
926
927static void
928dacleanup(struct cam_periph *periph)
929{
930 struct da_softc *softc;
--- 4 unchanged lines hidden (view full) ---
935 /*
936 * If we can't free the sysctl tree, oh well...
937 */
938 if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
939 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
940 xpt_print(periph->path, "can't remove sysctl context\n");
941 }
942 disk_destroy(softc->disk);
943
944 /*
945 * XXX Gotta drop the periph lock so that the drain can complete with
946 * deadlocking on the lock. Hopefully dropping here is safe.
947 */
948 cam_periph_unlock(periph);
949 callout_drain(&softc->sendordered_c);
950 cam_periph_lock(periph);
951 free(softc, M_DEVBUF);
952}
953
954static void
955daasync(void *callback_arg, u_int32_t code,
956 struct cam_path *path, void *arg)
957{
958 struct cam_periph *periph;
959
960 periph = (struct cam_periph *)callback_arg;
961 switch (code) {
962 case AC_FOUND_DEVICE:
963 {
964 struct ccb_getdev *cgd;
965 struct cam_sim *sim;
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 sim = xpt_path_sim(cgd->ccb_h.path);
983 status = cam_periph_alloc(daregister, daoninvalidate,
984 dacleanup, dastart,
985 "da", CAM_PERIPH_BIO,
986 cgd->ccb_h.path, daasync,
987 AC_FOUND_DEVICE, cgd);
988
989 if (status != CAM_REQ_CMP
990 && status != CAM_REQ_INPROG)
991 printf("daasync: Unable to attach to new device "
992 "due to status 0x%x\n", status);
993 break;
994 }
995 case AC_SENT_BDR:
996 case AC_BUS_RESET:
997 {
998 struct da_softc *softc;
999 struct ccb_hdr *ccbh;
1000
1001 softc = (struct da_softc *)periph->softc;
1002 /*
1003 * Don't fail on the expected unit attention
1004 * that will occur.
1005 */
1006 softc->flags |= DA_FLAG_RETRY_UA;
1007 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
1008 ccbh->ccb_state |= DA_CCB_RETRY_UA;
1009 /* FALLTHROUGH*/
1010 }
1011 default:
1012 cam_periph_async(periph, code, path, arg);
1013 break;
1014 }
1015}
1016
1017static void
1018dasysctlinit(void *context, int pending)
1019{
1020 struct cam_periph *periph;
1021 struct da_softc *softc;
1022 char tmpstr[80], tmpstr2[80];
1023
1024 periph = (struct cam_periph *)context;
1025 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
1026 return;
1027
1028 softc = (struct da_softc *)periph->softc;
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 cam_periph_release(periph);
1042 return;
1043 }
1044
1045 /*
1046 * Now register the sysctl handler, so the user can the value on
1047 * the fly.
1048 */
1049 SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
1050 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
1051 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
1052 "Minimum CDB size");
1053
1054 mtx_unlock(&Giant);
1055 cam_periph_release(periph);
1056}
1057
1058static int
1059dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
1060{
1061 int error, value;
1062
1063 value = *(int *)arg1;
--- 21 unchanged lines hidden (view full) ---
1085 *(int *)arg1 = value;
1086
1087 return (0);
1088}
1089
1090static cam_status
1091daregister(struct cam_periph *periph, void *arg)
1092{
1093 struct da_softc *softc;
1094 struct ccb_setasync csa;
1095 struct ccb_pathinq cpi;
1096 struct ccb_getdev *cgd;
1097 char tmpstr[80];
1098 caddr_t match;
1099
1100 cgd = (struct ccb_getdev *)arg;
--- 73 unchanged lines hidden (view full) ---
1174 softc->minimum_cmd_size = 10;
1175 else if ((softc->minimum_cmd_size > 10)
1176 && (softc->minimum_cmd_size <= 12))
1177 softc->minimum_cmd_size = 12;
1178 else if (softc->minimum_cmd_size > 12)
1179 softc->minimum_cmd_size = 16;
1180
1181 /*
1182 * Register this media as a disk
1183 */
1184
1185 mtx_unlock(periph->sim->mtx);
1186 softc->disk = disk_alloc();
1187 softc->disk->d_open = daopen;
1188 softc->disk->d_close = daclose;
1189 softc->disk->d_strategy = dastrategy;
1190 softc->disk->d_dump = dadump;
1191 softc->disk->d_name = "da";
1192 softc->disk->d_drv1 = periph;
1193 softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
1194 softc->disk->d_unit = periph->unit_number;
1195 softc->disk->d_flags = 0;
1196 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
1197 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
1198 disk_create(softc->disk, DISK_VERSION);
1199 mtx_lock(periph->sim->mtx);
1200
1201 /*
1202 * Add async callbacks for bus reset and
1203 * bus device reset calls. I don't bother
1204 * checking if this fails as, in most cases,
1205 * the system will function just fine without
1206 * them and the only alternative would be to
1207 * not attach the device on failure.
1208 */
1209 xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
1210 csa.ccb_h.func_code = XPT_SASYNC_CB;
1211 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
1212 csa.callback = daasync;
1213 csa.callback_arg = periph;
1214 xpt_action((union ccb *)&csa);
1215
1216 /*
1217 * Take an exclusive refcount on the periph while dastart is called
1218 * to finish the probe. The reference will be dropped in dadone at
1219 * the end of probe.
1220 */
1221 (void)cam_periph_hold(periph, PRIBIO);
1222 xpt_schedule(periph, /*priority*/5);
1223
1224 /*
1225 * Schedule a periodic event to occasionally send an
1226 * ordered tag to a device.
1227 */
1228 callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
1229 callout_reset(&softc->sendordered_c,
1230 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
1231 dasendorderedtag, softc);
1232
1233 return(CAM_REQ_CMP);
1234}
1235
1236static void
1237dastart(struct cam_periph *periph, union ccb *start_ccb)
1238{
1239 struct da_softc *softc;
1240
1241 softc = (struct da_softc *)periph->softc;
1242
1243 switch (softc->state) {
1244 case DA_STATE_NORMAL:
1245 {
1246 /* Pull a buffer from the queue and get going on it */
1247 struct bio *bp;
1248
1249 /*
1250 * See if there is a buf with work for us to do..
1251 */
1252 bp = bioq_first(&softc->bio_queue);
1253 if (periph->immediate_priority <= periph->pinfo.priority) {
1254 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1255 ("queuing for immediate ccb\n"));
1256 start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
1257 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1258 periph_links.sle);
1259 periph->immediate_priority = CAM_PRIORITY_NONE;
1260 wakeup(&periph->ccb_list);
1261 } else if (bp == NULL) {
1262 xpt_release_ccb(start_ccb);
1263 } else {
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 LIST_INSERT_HEAD(&softc->pending_ccbs,
1311 &start_ccb->ccb_h, periph_links.le);
1312 softc->outstanding_cmds++;
1313
1314 /* We expect a unit attention from this device */
1315 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
1316 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
1317 softc->flags &= ~DA_FLAG_RETRY_UA;
1318 }
1319
1320 start_ccb->ccb_h.ccb_bp = bp;
1321 bp = bioq_first(&softc->bio_queue);
1322
1323 xpt_action(start_ccb);
1324 }
1325
1326 if (bp != NULL) {
1327 /* Have more work to do, so ensure we stay scheduled */
1328 xpt_schedule(periph, /* XXX priority */1);
1329 }
--- 108 unchanged lines hidden (view full) ---
1438 struct ccb_scsiio *csio;
1439
1440 softc = (struct da_softc *)periph->softc;
1441 csio = &done_ccb->csio;
1442 switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
1443 case DA_CCB_BUFFER_IO:
1444 {
1445 struct bio *bp;
1446
1447 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
1448 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1449 int error;
1450 int sf;
1451
1452 if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
1453 sf = SF_RETRY_UA;
1454 else
1455 sf = 0;
1456
1457 error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
1458 if (error == ERESTART) {
1459 /*
1460 * A retry was scheuled, so
1461 * just return.
1462 */
1463 return;
1464 }
1465 if (error != 0) {
1466
1467 if (error == ENXIO) {
1468 /*
1469 * Catastrophic error. Mark our pack as
1470 * invalid.
1471 */
1472 /*
1473 * XXX See if this is really a media
1474 * XXX change first?
--- 4 unchanged lines hidden (view full) ---
1479 }
1480
1481 /*
1482 * return all queued I/O with EIO, so that
1483 * the client can retry these I/Os in the
1484 * proper order should it attempt to recover.
1485 */
1486 bioq_flush(&softc->bio_queue, NULL, EIO);
1487 bp->bio_error = error;
1488 bp->bio_resid = bp->bio_bcount;
1489 bp->bio_flags |= BIO_ERROR;
1490 } else {
1491 bp->bio_resid = csio->resid;
1492 bp->bio_error = 0;
1493 if (bp->bio_resid != 0)
1494 bp->bio_flags |= BIO_ERROR;
--- 11 unchanged lines hidden (view full) ---
1506 if (csio->resid > 0)
1507 bp->bio_flags |= BIO_ERROR;
1508 }
1509
1510 /*
1511 * Block out any asyncronous callbacks
1512 * while we touch the pending ccb list.
1513 */
1514 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1515 softc->outstanding_cmds--;
1516 if (softc->outstanding_cmds == 0)
1517 softc->flags |= DA_FLAG_WENT_IDLE;
1518
1519 biodone(bp);
1520 break;
1521 }
1522 case DA_CCB_PROBE:
1523 case DA_CCB_PROBE2:
1524 {
1525 struct scsi_read_capacity_data *rdcap;
--- 169 unchanged lines hidden (view full) ---
1695 * Since our peripheral may be invalidated by an error
1696 * above or an external event, we must release our CCB
1697 * before releasing the probe lock on the peripheral.
1698 * The peripheral will only go away once the last lock
1699 * is removed, and we need it around for the CCB release
1700 * operation.
1701 */
1702 xpt_release_ccb(done_ccb);
1703 cam_periph_unhold(periph);
1704 return;
1705 }
1706 case DA_CCB_WAITING:
1707 {
1708 /* Caller will release the CCB */
1709 wakeup(&done_ccb->ccb_h.cbfcnp);
1710 return;
1711 }
--- 106 unchanged lines hidden (view full) ---
1818 error = 0;
1819 sense_flags = SF_RETRY_UA;
1820 if (softc->flags & DA_FLAG_PACK_REMOVABLE)
1821 sense_flags |= SF_NO_PRINT;
1822
1823 /* Do a read capacity */
1824 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
1825 M_TEMP,
1826 M_NOWAIT);
1827 if (rcap == NULL)
1828 return (ENOMEM);
1829
1830 ccb = cam_periph_getccb(periph, /*priority*/1);
1831 scsi_read_capacity(&ccb->csio,
1832 /*retries*/4,
1833 /*cbfncp*/dadone,
1834 MSG_SIMPLE_Q_TAG,
1835 rcap,
1836 SSD_FULL_SIZE,
--- 109 unchanged lines hidden (view full) ---
1946 dp->secs_per_track = ccg.secs_per_track;
1947 dp->cylinders = ccg.cylinders;
1948 }
1949}
1950
1951static void
1952dasendorderedtag(void *arg)
1953{
1954 struct da_softc *softc = arg;
1955
1956 if (da_send_ordered) {
1957 if ((softc->ordered_tag_count == 0)
1958 && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
1959 softc->flags |= DA_FLAG_NEED_OTAG;
1960 }
1961 if (softc->outstanding_cmds > 0)
1962 softc->flags &= ~DA_FLAG_WENT_IDLE;
1963
1964 softc->ordered_tag_count = 0;
1965 }
1966 /* Queue us up again */
1967 callout_reset(&softc->sendordered_c,
1968 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
1969 dasendorderedtag, softc);
1970}
1971
1972/*
1973 * Step through all DA peripheral drivers, and if the device is still open,
1974 * sync the disk cache to physical media.
1975 */
1976static void
1977dashutdown(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 168752 2007-04-15 08:49:19Z scottl $");
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#include <sys/lock.h>
41#include <sys/mutex.h>
42#endif /* _KERNEL */
43
44#include <sys/devicestat.h>
45#include <sys/conf.h>
46#include <sys/eventhandler.h>
47#include <sys/malloc.h>
48#include <sys/cons.h>
49
--- 8 unchanged lines hidden (view full) ---
58#include <stdio.h>
59#include <string.h>
60#endif /* _KERNEL */
61
62#include <cam/cam.h>
63#include <cam/cam_ccb.h>
64#include <cam/cam_periph.h>
65#include <cam/cam_xpt_periph.h>
66#include <cam/cam_sim.h>
67
68#include <cam/scsi/scsi_message.h>
69
70#ifndef _KERNEL
71#include <cam/scsi/scsi_da.h>
72#endif /* !_KERNEL */
73
74#ifdef _KERNEL
--- 56 unchanged lines hidden (view full) ---
131 int ordered_tag_count;
132 int outstanding_cmds;
133 struct disk_params params;
134 struct disk *disk;
135 union ccb saved_ccb;
136 struct task sysctl_task;
137 struct sysctl_ctx_list sysctl_ctx;
138 struct sysctl_oid *sysctl_tree;
139 struct callout sendordered_c;
140};
141
142struct da_quirk_entry {
143 struct scsi_inquiry_pattern inq_pat;
144 da_quirks quirks;
145};
146
147static const char quantum[] = "QUANTUM";
--- 402 unchanged lines hidden (view full) ---
550static struct periph_driver dadriver =
551{
552 dainit, "da",
553 TAILQ_HEAD_INITIALIZER(dadriver.units), /* generation */ 0
554};
555
556PERIPHDRIVER_DECLARE(da, dadriver);
557
558static int
559daopen(struct disk *dp)
560{
561 struct cam_periph *periph;
562 struct da_softc *softc;
563 int unit;
564 int error;
565
566 periph = (struct cam_periph *)dp->d_drv1;
567 if (periph == NULL) {
568 return (ENXIO);
569 }
570
571 if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
572 return(ENXIO);
573 }
574
575 cam_periph_lock(periph);
576 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
577 cam_periph_unlock(periph);
578 cam_periph_release(periph);
579 return (error);
580 }
581
582 unit = periph->unit_number;
583 softc = (struct da_softc *)periph->softc;
584 softc->flags |= DA_FLAG_OPEN;
585
586 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
587 ("daopen: disk=%s%d (unit %d)\n", dp->d_name, dp->d_unit,
588 unit));
589
590 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0) {
591 /* Invalidate our pack information. */
592 softc->flags &= ~DA_FLAG_PACK_INVALID;
593 }
594
595 error = dagetcapacity(periph);
596
597 if (error == 0) {
598
599 softc->disk->d_sectorsize = softc->params.secsize;
600 softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
601 /* XXX: these are not actually "firmware" values, so they may be wrong */
--- 6 unchanged lines hidden (view full) ---
608 if (error == 0) {
609 if ((softc->flags & DA_FLAG_PACK_REMOVABLE) != 0 &&
610 (softc->quirks & DA_Q_NO_PREVENT) == 0)
611 daprevent(periph, PR_PREVENT);
612 } else {
613 softc->flags &= ~DA_FLAG_OPEN;
614 cam_periph_release(periph);
615 }
616 cam_periph_unhold(periph);
617 cam_periph_unlock(periph);
618 return (error);
619}
620
621static int
622daclose(struct disk *dp)
623{
624 struct cam_periph *periph;
625 struct da_softc *softc;
626 int error;
627
628 periph = (struct cam_periph *)dp->d_drv1;
629 if (periph == NULL)
630 return (ENXIO);
631
632 cam_periph_lock(periph);
633 if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
634 cam_periph_unlock(periph);
635 cam_periph_release(periph);
636 return (error);
637 }
638
639 softc = (struct da_softc *)periph->softc;
640
641 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
642 union ccb *ccb;
643
644 ccb = cam_periph_getccb(periph, /*priority*/1);
645
646 scsi_synchronize_cache(&ccb->csio,
647 /*retries*/1,
648 /*cbfcnp*/dadone,
--- 45 unchanged lines hidden (view full) ---
694 * If we've got removeable media, mark the blocksize as
695 * unavailable, since it could change when new media is
696 * inserted.
697 */
698 softc->disk->d_devstat->flags |= DEVSTAT_BS_UNAVAILABLE;
699 }
700
701 softc->flags &= ~DA_FLAG_OPEN;
702 cam_periph_unhold(periph);
703 cam_periph_unlock(periph);
704 cam_periph_release(periph);
705 return (0);
706}
707
708/*
709 * Actually translate the requested transfer into one the physical driver
710 * can understand. The transfer is described by a buf and will include
711 * only one physical transfer.
712 */
713static void
714dastrategy(struct bio *bp)
715{
716 struct cam_periph *periph;
717 struct da_softc *softc;
718
719 periph = (struct cam_periph *)bp->bio_disk->d_drv1;
720 if (periph == NULL) {
721 biofinish(bp, NULL, ENXIO);
722 return;
723 }
724 softc = (struct da_softc *)periph->softc;
725
726 cam_periph_lock(periph);
727
728#if 0
729 /*
730 * check it's not too big a transfer for our adapter
731 */
732 scsi_minphys(bp,&sd_switch);
733#endif
734
735 /*
736 * Mask interrupts so that the pack cannot be invalidated until
737 * after we are in the queue. Otherwise, we might not properly
738 * clean up one of the buffers.
739 */
740
741 /*
742 * If the device has been made invalid, error out
743 */
744 if ((softc->flags & DA_FLAG_PACK_INVALID)) {
745 cam_periph_unlock(periph);
746 biofinish(bp, NULL, ENXIO);
747 return;
748 }
749
750 /*
751 * Place it in the queue of disk activities for this disk
752 */
753 bioq_disksort(&softc->bio_queue, bp);
754
755 /*
756 * Schedule ourselves for performing the work.
757 */
758 xpt_schedule(periph, /* XXX priority */1);
759 cam_periph_unlock(periph);
760
761 return;
762}
763
764static int
765dadump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
766{
767 struct cam_periph *periph;
--- 8 unchanged lines hidden (view full) ---
776 return (ENXIO);
777 softc = (struct da_softc *)periph->softc;
778 secsize = softc->params.secsize;
779
780 if ((softc->flags & DA_FLAG_PACK_INVALID) != 0)
781 return (ENXIO);
782
783 if (length > 0) {
784 periph->flags |= CAM_PERIPH_POLLED;
785 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
786 csio.ccb_h.ccb_state = DA_CCB_DUMP;
787 scsi_read_write(&csio,
788 /*retries*/1,
789 dadone,
790 MSG_ORDERED_Q_TAG,
791 /*read*/FALSE,
792 /*byte2*/0,
--- 9 unchanged lines hidden (view full) ---
802 if ((csio.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
803 printf("Aborting dump due to I/O error.\n");
804 if ((csio.ccb_h.status & CAM_STATUS_MASK) ==
805 CAM_SCSI_STATUS_ERROR)
806 scsi_sense_print(&csio);
807 else
808 printf("status == 0x%x, scsi status == 0x%x\n",
809 csio.ccb_h.status, csio.scsi_status);
810 periph->flags |= CAM_PERIPH_POLLED;
811 return(EIO);
812 }
813 return(0);
814 }
815
816 /*
817 * Sync the disk cache contents to the physical media.
818 */
819 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0) {
820
821 xpt_setup_ccb(&csio.ccb_h, periph->path, /*priority*/1);
822 csio.ccb_h.ccb_state = DA_CCB_DUMP;
--- 22 unchanged lines hidden (view full) ---
845 } else {
846 xpt_print(periph->path, "Synchronize cache "
847 "failed, status == 0x%x, scsi status == "
848 "0x%x\n", csio.ccb_h.status,
849 csio.scsi_status);
850 }
851 }
852 }
853 periph->flags &= ~CAM_PERIPH_POLLED;
854 return (0);
855}
856
857static void
858dainit(void)
859{
860 cam_status status;
861 struct cam_path *path;
862
863 /*
864 * Install a global async callback. This callback will
865 * receive async callbacks like "new device found".
866 */
867 status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID,
868 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
869
870 if (status == CAM_REQ_CMP) {
--- 9 unchanged lines hidden (view full) ---
880 xpt_free_path(path);
881 }
882
883 if (status != CAM_REQ_CMP) {
884 printf("da: Failed to attach master async callback "
885 "due to status 0x%x!\n", status);
886 } else if (da_send_ordered) {
887
888 /* Register our shutdown event handler */
889 if ((EVENTHANDLER_REGISTER(shutdown_post_sync, dashutdown,
890 NULL, SHUTDOWN_PRI_DEFAULT)) == NULL)
891 printf("dainit: shutdown event registration failed!\n");
892 }
893}
894
895static void
896daoninvalidate(struct cam_periph *periph)
897{
898 struct da_softc *softc;
899 struct ccb_setasync csa;
900
901 softc = (struct da_softc *)periph->softc;
902
903 /*
904 * De-register any async callbacks.
905 */
906 xpt_setup_ccb(&csa.ccb_h, periph->path,
907 /* priority */ 5);
908 csa.ccb_h.func_code = XPT_SASYNC_CB;
909 csa.event_enable = 0;
910 csa.callback = daasync;
911 csa.callback_arg = periph;
912 xpt_action((union ccb *)&csa);
913
914 softc->flags |= DA_FLAG_PACK_INVALID;
915
916 /*
917 * Return all queued I/O with ENXIO.
918 * XXX Handle any transactions queued to the card
919 * with XPT_ABORT_CCB.
920 */
921 bioq_flush(&softc->bio_queue, NULL, ENXIO);
922
923 disk_gone(softc->disk);
924 xpt_print(periph->path, "lost device\n");
925}
926
927static void
928dacleanup(struct cam_periph *periph)
929{
930 struct da_softc *softc;
--- 4 unchanged lines hidden (view full) ---
935 /*
936 * If we can't free the sysctl tree, oh well...
937 */
938 if ((softc->flags & DA_FLAG_SCTX_INIT) != 0
939 && sysctl_ctx_free(&softc->sysctl_ctx) != 0) {
940 xpt_print(periph->path, "can't remove sysctl context\n");
941 }
942 disk_destroy(softc->disk);
943
944 /*
945 * XXX Gotta drop the periph lock so that the drain can complete with
946 * deadlocking on the lock. Hopefully dropping here is safe.
947 */
948 cam_periph_unlock(periph);
949 callout_drain(&softc->sendordered_c);
950 cam_periph_lock(periph);
951 free(softc, M_DEVBUF);
952}
953
954static void
955daasync(void *callback_arg, u_int32_t code,
956 struct cam_path *path, void *arg)
957{
958 struct cam_periph *periph;
959
960 periph = (struct cam_periph *)callback_arg;
961 switch (code) {
962 case AC_FOUND_DEVICE:
963 {
964 struct ccb_getdev *cgd;
965 struct cam_sim *sim;
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 sim = xpt_path_sim(cgd->ccb_h.path);
983 status = cam_periph_alloc(daregister, daoninvalidate,
984 dacleanup, dastart,
985 "da", CAM_PERIPH_BIO,
986 cgd->ccb_h.path, daasync,
987 AC_FOUND_DEVICE, cgd);
988
989 if (status != CAM_REQ_CMP
990 && status != CAM_REQ_INPROG)
991 printf("daasync: Unable to attach to new device "
992 "due to status 0x%x\n", status);
993 break;
994 }
995 case AC_SENT_BDR:
996 case AC_BUS_RESET:
997 {
998 struct da_softc *softc;
999 struct ccb_hdr *ccbh;
1000
1001 softc = (struct da_softc *)periph->softc;
1002 /*
1003 * Don't fail on the expected unit attention
1004 * that will occur.
1005 */
1006 softc->flags |= DA_FLAG_RETRY_UA;
1007 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
1008 ccbh->ccb_state |= DA_CCB_RETRY_UA;
1009 /* FALLTHROUGH*/
1010 }
1011 default:
1012 cam_periph_async(periph, code, path, arg);
1013 break;
1014 }
1015}
1016
1017static void
1018dasysctlinit(void *context, int pending)
1019{
1020 struct cam_periph *periph;
1021 struct da_softc *softc;
1022 char tmpstr[80], tmpstr2[80];
1023
1024 periph = (struct cam_periph *)context;
1025 if (cam_periph_acquire(periph) != CAM_REQ_CMP)
1026 return;
1027
1028 softc = (struct da_softc *)periph->softc;
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 cam_periph_release(periph);
1042 return;
1043 }
1044
1045 /*
1046 * Now register the sysctl handler, so the user can the value on
1047 * the fly.
1048 */
1049 SYSCTL_ADD_PROC(&softc->sysctl_ctx,SYSCTL_CHILDREN(softc->sysctl_tree),
1050 OID_AUTO, "minimum_cmd_size", CTLTYPE_INT | CTLFLAG_RW,
1051 &softc->minimum_cmd_size, 0, dacmdsizesysctl, "I",
1052 "Minimum CDB size");
1053
1054 mtx_unlock(&Giant);
1055 cam_periph_release(periph);
1056}
1057
1058static int
1059dacmdsizesysctl(SYSCTL_HANDLER_ARGS)
1060{
1061 int error, value;
1062
1063 value = *(int *)arg1;
--- 21 unchanged lines hidden (view full) ---
1085 *(int *)arg1 = value;
1086
1087 return (0);
1088}
1089
1090static cam_status
1091daregister(struct cam_periph *periph, void *arg)
1092{
1093 struct da_softc *softc;
1094 struct ccb_setasync csa;
1095 struct ccb_pathinq cpi;
1096 struct ccb_getdev *cgd;
1097 char tmpstr[80];
1098 caddr_t match;
1099
1100 cgd = (struct ccb_getdev *)arg;
--- 73 unchanged lines hidden (view full) ---
1174 softc->minimum_cmd_size = 10;
1175 else if ((softc->minimum_cmd_size > 10)
1176 && (softc->minimum_cmd_size <= 12))
1177 softc->minimum_cmd_size = 12;
1178 else if (softc->minimum_cmd_size > 12)
1179 softc->minimum_cmd_size = 16;
1180
1181 /*
1182 * Register this media as a disk
1183 */
1184
1185 mtx_unlock(periph->sim->mtx);
1186 softc->disk = disk_alloc();
1187 softc->disk->d_open = daopen;
1188 softc->disk->d_close = daclose;
1189 softc->disk->d_strategy = dastrategy;
1190 softc->disk->d_dump = dadump;
1191 softc->disk->d_name = "da";
1192 softc->disk->d_drv1 = periph;
1193 softc->disk->d_maxsize = DFLTPHYS; /* XXX: probably not arbitrary */
1194 softc->disk->d_unit = periph->unit_number;
1195 softc->disk->d_flags = 0;
1196 if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
1197 softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
1198 disk_create(softc->disk, DISK_VERSION);
1199 mtx_lock(periph->sim->mtx);
1200
1201 /*
1202 * Add async callbacks for bus reset and
1203 * bus device reset calls. I don't bother
1204 * checking if this fails as, in most cases,
1205 * the system will function just fine without
1206 * them and the only alternative would be to
1207 * not attach the device on failure.
1208 */
1209 xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5);
1210 csa.ccb_h.func_code = XPT_SASYNC_CB;
1211 csa.event_enable = AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE;
1212 csa.callback = daasync;
1213 csa.callback_arg = periph;
1214 xpt_action((union ccb *)&csa);
1215
1216 /*
1217 * Take an exclusive refcount on the periph while dastart is called
1218 * to finish the probe. The reference will be dropped in dadone at
1219 * the end of probe.
1220 */
1221 (void)cam_periph_hold(periph, PRIBIO);
1222 xpt_schedule(periph, /*priority*/5);
1223
1224 /*
1225 * Schedule a periodic event to occasionally send an
1226 * ordered tag to a device.
1227 */
1228 callout_init_mtx(&softc->sendordered_c, periph->sim->mtx, 0);
1229 callout_reset(&softc->sendordered_c,
1230 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
1231 dasendorderedtag, softc);
1232
1233 return(CAM_REQ_CMP);
1234}
1235
1236static void
1237dastart(struct cam_periph *periph, union ccb *start_ccb)
1238{
1239 struct da_softc *softc;
1240
1241 softc = (struct da_softc *)periph->softc;
1242
1243 switch (softc->state) {
1244 case DA_STATE_NORMAL:
1245 {
1246 /* Pull a buffer from the queue and get going on it */
1247 struct bio *bp;
1248
1249 /*
1250 * See if there is a buf with work for us to do..
1251 */
1252 bp = bioq_first(&softc->bio_queue);
1253 if (periph->immediate_priority <= periph->pinfo.priority) {
1254 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1255 ("queuing for immediate ccb\n"));
1256 start_ccb->ccb_h.ccb_state = DA_CCB_WAITING;
1257 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1258 periph_links.sle);
1259 periph->immediate_priority = CAM_PRIORITY_NONE;
1260 wakeup(&periph->ccb_list);
1261 } else if (bp == NULL) {
1262 xpt_release_ccb(start_ccb);
1263 } else {
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 LIST_INSERT_HEAD(&softc->pending_ccbs,
1311 &start_ccb->ccb_h, periph_links.le);
1312 softc->outstanding_cmds++;
1313
1314 /* We expect a unit attention from this device */
1315 if ((softc->flags & DA_FLAG_RETRY_UA) != 0) {
1316 start_ccb->ccb_h.ccb_state |= DA_CCB_RETRY_UA;
1317 softc->flags &= ~DA_FLAG_RETRY_UA;
1318 }
1319
1320 start_ccb->ccb_h.ccb_bp = bp;
1321 bp = bioq_first(&softc->bio_queue);
1322
1323 xpt_action(start_ccb);
1324 }
1325
1326 if (bp != NULL) {
1327 /* Have more work to do, so ensure we stay scheduled */
1328 xpt_schedule(periph, /* XXX priority */1);
1329 }
--- 108 unchanged lines hidden (view full) ---
1438 struct ccb_scsiio *csio;
1439
1440 softc = (struct da_softc *)periph->softc;
1441 csio = &done_ccb->csio;
1442 switch (csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK) {
1443 case DA_CCB_BUFFER_IO:
1444 {
1445 struct bio *bp;
1446
1447 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
1448 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1449 int error;
1450 int sf;
1451
1452 if ((csio->ccb_h.ccb_state & DA_CCB_RETRY_UA) != 0)
1453 sf = SF_RETRY_UA;
1454 else
1455 sf = 0;
1456
1457 error = daerror(done_ccb, CAM_RETRY_SELTO, sf);
1458 if (error == ERESTART) {
1459 /*
1460 * A retry was scheuled, so
1461 * just return.
1462 */
1463 return;
1464 }
1465 if (error != 0) {
1466
1467 if (error == ENXIO) {
1468 /*
1469 * Catastrophic error. Mark our pack as
1470 * invalid.
1471 */
1472 /*
1473 * XXX See if this is really a media
1474 * XXX change first?
--- 4 unchanged lines hidden (view full) ---
1479 }
1480
1481 /*
1482 * return all queued I/O with EIO, so that
1483 * the client can retry these I/Os in the
1484 * proper order should it attempt to recover.
1485 */
1486 bioq_flush(&softc->bio_queue, NULL, EIO);
1487 bp->bio_error = error;
1488 bp->bio_resid = bp->bio_bcount;
1489 bp->bio_flags |= BIO_ERROR;
1490 } else {
1491 bp->bio_resid = csio->resid;
1492 bp->bio_error = 0;
1493 if (bp->bio_resid != 0)
1494 bp->bio_flags |= BIO_ERROR;
--- 11 unchanged lines hidden (view full) ---
1506 if (csio->resid > 0)
1507 bp->bio_flags |= BIO_ERROR;
1508 }
1509
1510 /*
1511 * Block out any asyncronous callbacks
1512 * while we touch the pending ccb list.
1513 */
1514 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
1515 softc->outstanding_cmds--;
1516 if (softc->outstanding_cmds == 0)
1517 softc->flags |= DA_FLAG_WENT_IDLE;
1518
1519 biodone(bp);
1520 break;
1521 }
1522 case DA_CCB_PROBE:
1523 case DA_CCB_PROBE2:
1524 {
1525 struct scsi_read_capacity_data *rdcap;
--- 169 unchanged lines hidden (view full) ---
1695 * Since our peripheral may be invalidated by an error
1696 * above or an external event, we must release our CCB
1697 * before releasing the probe lock on the peripheral.
1698 * The peripheral will only go away once the last lock
1699 * is removed, and we need it around for the CCB release
1700 * operation.
1701 */
1702 xpt_release_ccb(done_ccb);
1703 cam_periph_unhold(periph);
1704 return;
1705 }
1706 case DA_CCB_WAITING:
1707 {
1708 /* Caller will release the CCB */
1709 wakeup(&done_ccb->ccb_h.cbfcnp);
1710 return;
1711 }
--- 106 unchanged lines hidden (view full) ---
1818 error = 0;
1819 sense_flags = SF_RETRY_UA;
1820 if (softc->flags & DA_FLAG_PACK_REMOVABLE)
1821 sense_flags |= SF_NO_PRINT;
1822
1823 /* Do a read capacity */
1824 rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcaplong),
1825 M_TEMP,
1826 M_NOWAIT);
1827 if (rcap == NULL)
1828 return (ENOMEM);
1829
1830 ccb = cam_periph_getccb(periph, /*priority*/1);
1831 scsi_read_capacity(&ccb->csio,
1832 /*retries*/4,
1833 /*cbfncp*/dadone,
1834 MSG_SIMPLE_Q_TAG,
1835 rcap,
1836 SSD_FULL_SIZE,
--- 109 unchanged lines hidden (view full) ---
1946 dp->secs_per_track = ccg.secs_per_track;
1947 dp->cylinders = ccg.cylinders;
1948 }
1949}
1950
1951static void
1952dasendorderedtag(void *arg)
1953{
1954 struct da_softc *softc = arg;
1955
1956 if (da_send_ordered) {
1957 if ((softc->ordered_tag_count == 0)
1958 && ((softc->flags & DA_FLAG_WENT_IDLE) == 0)) {
1959 softc->flags |= DA_FLAG_NEED_OTAG;
1960 }
1961 if (softc->outstanding_cmds > 0)
1962 softc->flags &= ~DA_FLAG_WENT_IDLE;
1963
1964 softc->ordered_tag_count = 0;
1965 }
1966 /* Queue us up again */
1967 callout_reset(&softc->sendordered_c,
1968 (DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
1969 dasendorderedtag, softc);
1970}
1971
1972/*
1973 * Step through all DA peripheral drivers, and if the device is still open,
1974 * sync the disk cache to physical media.
1975 */
1976static void
1977dashutdown(void * arg, int howto)
--- 94 unchanged lines hidden ---