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 --- |