xref: /freebsd/tools/tools/vhba/faulty/vhba_faulty.c (revision 2a63c3be)
18d7b838eSMatt Jacob /*-
28d7b838eSMatt Jacob  * Copyright (c) 2010 by Panasas, Inc.
38d7b838eSMatt Jacob  * All rights reserved.
48d7b838eSMatt Jacob  *
58d7b838eSMatt Jacob  * Redistribution and use in source and binary forms, with or without
68d7b838eSMatt Jacob  * modification, are permitted provided that the following conditions
78d7b838eSMatt Jacob  * are met:
88d7b838eSMatt Jacob  * 1. Redistributions of source code must retain the above copyright
98d7b838eSMatt Jacob  *    notice immediately at the beginning of the file, without modification,
108d7b838eSMatt Jacob  *    this list of conditions, and the following disclaimer.
118d7b838eSMatt Jacob  * 2. The name of the author may not be used to endorse or promote products
128d7b838eSMatt Jacob  *    derived from this software without specific prior written permission.
138d7b838eSMatt Jacob  *
148d7b838eSMatt Jacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
158d7b838eSMatt Jacob  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168d7b838eSMatt Jacob  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
178d7b838eSMatt Jacob  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
188d7b838eSMatt Jacob  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
198d7b838eSMatt Jacob  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208d7b838eSMatt Jacob  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
218d7b838eSMatt Jacob  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
228d7b838eSMatt Jacob  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
238d7b838eSMatt Jacob  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
248d7b838eSMatt Jacob  * SUCH DAMAGE.
258d7b838eSMatt Jacob  */
268d7b838eSMatt Jacob /*
278d7b838eSMatt Jacob  * "Faulty" Device. Victimize random commands with a Selection Timeout.
288d7b838eSMatt Jacob  */
298d7b838eSMatt Jacob #include "vhba.h"
308d7b838eSMatt Jacob 
318d7b838eSMatt Jacob #define	MAX_TGT		VHBA_MAXTGT
328d7b838eSMatt Jacob #define	MAX_LUN		4
338d7b838eSMatt Jacob 
348d7b838eSMatt Jacob #define	DISK_SIZE	32
358d7b838eSMatt Jacob #define	DISK_SHIFT	9
368d7b838eSMatt Jacob #define	DISK_NBLKS	((DISK_SIZE << 20) >> DISK_SHIFT)
378d7b838eSMatt Jacob #define	PSEUDO_SPT	64
388d7b838eSMatt Jacob #define	PSEUDO_HDS	64
398d7b838eSMatt Jacob #define	PSEUDO_SPC	(PSEUDO_SPT * PSEUDO_HDS)
408d7b838eSMatt Jacob 
418d7b838eSMatt Jacob typedef struct {
428d7b838eSMatt Jacob 	vhba_softc_t *	vhba;
438d7b838eSMatt Jacob 	uint8_t *	disk;
448d7b838eSMatt Jacob 	size_t		disk_size;
458d7b838eSMatt Jacob 	uint32_t	ctr;
468d7b838eSMatt Jacob 	uint32_t	dead;
478d7b838eSMatt Jacob 	struct task	qt;
488d7b838eSMatt Jacob } faulty_t;
498d7b838eSMatt Jacob 
508d7b838eSMatt Jacob static void vhba_task(void *, int);
518d7b838eSMatt Jacob static void faulty_act(faulty_t *, struct ccb_scsiio *);
528d7b838eSMatt Jacob 
538d7b838eSMatt Jacob void
vhba_init(vhba_softc_t * vhba)548d7b838eSMatt Jacob vhba_init(vhba_softc_t *vhba)
558d7b838eSMatt Jacob {
568d7b838eSMatt Jacob 	static faulty_t vhbastatic;
578d7b838eSMatt Jacob 	vhbastatic.vhba = vhba;
588d7b838eSMatt Jacob 	vhbastatic.disk_size = DISK_SIZE << 20;
598d7b838eSMatt Jacob 	vhbastatic.disk = malloc(vhbastatic.disk_size, M_DEVBUF, M_WAITOK|M_ZERO);
608d7b838eSMatt Jacob 	vhba->private = &vhbastatic;
618d7b838eSMatt Jacob 	vhbastatic.ctr = (arc4random() & 0xffff) + 1;
628d7b838eSMatt Jacob 	TASK_INIT(&vhbastatic.qt, 0, vhba_task, &vhbastatic);
638d7b838eSMatt Jacob }
648d7b838eSMatt Jacob 
658d7b838eSMatt Jacob 
668d7b838eSMatt Jacob void
vhba_fini(vhba_softc_t * vhba)678d7b838eSMatt Jacob vhba_fini(vhba_softc_t *vhba)
688d7b838eSMatt Jacob {
698d7b838eSMatt Jacob 	faulty_t *vhbas = vhba->private;
708d7b838eSMatt Jacob 	vhba->private = NULL;
718d7b838eSMatt Jacob 	free(vhbas->disk, M_DEVBUF);
728d7b838eSMatt Jacob }
738d7b838eSMatt Jacob 
748d7b838eSMatt Jacob void
vhba_kick(vhba_softc_t * vhba)758d7b838eSMatt Jacob vhba_kick(vhba_softc_t *vhba)
768d7b838eSMatt Jacob {
778d7b838eSMatt Jacob 	faulty_t *vhbas = vhba->private;
788d7b838eSMatt Jacob 	taskqueue_enqueue(taskqueue_swi, &vhbas->qt);
798d7b838eSMatt Jacob }
808d7b838eSMatt Jacob 
818d7b838eSMatt Jacob static void
vhba_task(void * arg,int pending)828d7b838eSMatt Jacob vhba_task(void *arg, int pending)
838d7b838eSMatt Jacob {
848d7b838eSMatt Jacob 	faulty_t *vhbas = arg;
858d7b838eSMatt Jacob 	struct ccb_hdr *ccbh;
868d7b838eSMatt Jacob 
878d7b838eSMatt Jacob 	mtx_lock(&vhbas->vhba->lock);
888d7b838eSMatt Jacob 	while ((ccbh = TAILQ_FIRST(&vhbas->vhba->actv)) != NULL) {
898d7b838eSMatt Jacob 		TAILQ_REMOVE(&vhbas->vhba->actv, ccbh, sim_links.tqe);
908d7b838eSMatt Jacob                 faulty_act(vhbas, (struct ccb_scsiio *)ccbh);
918d7b838eSMatt Jacob 		if (--vhbas->ctr == 0) {
928d7b838eSMatt Jacob 			vhbas->dead = 1;
938d7b838eSMatt Jacob 			vhbas->ctr = (arc4random() & 0xff) + 1;
948d7b838eSMatt Jacob 		}
958d7b838eSMatt Jacob 	}
968d7b838eSMatt Jacob 	while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) {
978d7b838eSMatt Jacob 		TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe);
988d7b838eSMatt Jacob 		xpt_done((union ccb *)ccbh);
998d7b838eSMatt Jacob 	}
1008d7b838eSMatt Jacob 	mtx_unlock(&vhbas->vhba->lock);
1018d7b838eSMatt Jacob }
1028d7b838eSMatt Jacob 
1038d7b838eSMatt Jacob static void
faulty_act(faulty_t * vhbas,struct ccb_scsiio * csio)1048d7b838eSMatt Jacob faulty_act(faulty_t *vhbas, struct ccb_scsiio *csio)
1058d7b838eSMatt Jacob {
1068d7b838eSMatt Jacob 	char junk[128];
1078d7b838eSMatt Jacob 	cam_status camstatus;
1088d7b838eSMatt Jacob 	uint8_t *cdb, *ptr, status;
1098d7b838eSMatt Jacob 	uint32_t data_len;
1108d7b838eSMatt Jacob 	uint64_t off;
1118d7b838eSMatt Jacob 
1128d7b838eSMatt Jacob 	data_len = 0;
1138d7b838eSMatt Jacob 	status = SCSI_STATUS_OK;
1148d7b838eSMatt Jacob 
1158d7b838eSMatt Jacob 	memset(&csio->sense_data, 0, sizeof (csio->sense_data));
1168d7b838eSMatt Jacob 	cdb = csio->cdb_io.cdb_bytes;
1178d7b838eSMatt Jacob 
1188d7b838eSMatt Jacob 	if (csio->ccb_h.target_id >=  MAX_TGT) {
1198d7b838eSMatt Jacob 		vhba_set_status(&csio->ccb_h, CAM_SEL_TIMEOUT);
1208d7b838eSMatt Jacob 		TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
1218d7b838eSMatt Jacob 		return;
1228d7b838eSMatt Jacob 	}
1238d7b838eSMatt Jacob 	if (vhbas->dead) {
1248d7b838eSMatt Jacob 		vhbas->dead = 0;
1258d7b838eSMatt Jacob 		vhba_set_status(&csio->ccb_h, CAM_SEL_TIMEOUT);
1268d7b838eSMatt Jacob 		TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
1278d7b838eSMatt Jacob 		return;
1288d7b838eSMatt Jacob 	}
1298d7b838eSMatt Jacob 	if (csio->ccb_h.target_lun >= MAX_LUN && cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) {
1308d7b838eSMatt Jacob 		vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x25, 0x0);
1318d7b838eSMatt Jacob 		TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
1328d7b838eSMatt Jacob 		return;
1338d7b838eSMatt Jacob 	}
1348d7b838eSMatt Jacob 
1358d7b838eSMatt Jacob 	switch (cdb[0]) {
1368d7b838eSMatt Jacob 	case MODE_SENSE:
1378d7b838eSMatt Jacob 	case MODE_SENSE_10:
1388d7b838eSMatt Jacob 	{
1398d7b838eSMatt Jacob 		unsigned int nbyte;
1408d7b838eSMatt Jacob 		uint8_t page = cdb[2] & SMS_PAGE_CODE;
1418d7b838eSMatt Jacob 		uint8_t pgctl = cdb[2] & SMS_PAGE_CTRL_MASK;
1428d7b838eSMatt Jacob 
1438d7b838eSMatt Jacob 		switch (page) {
1448d7b838eSMatt Jacob 		case SMS_FORMAT_DEVICE_PAGE:
1458d7b838eSMatt Jacob 		case SMS_GEOMETRY_PAGE:
1468d7b838eSMatt Jacob 		case SMS_CACHE_PAGE:
1478d7b838eSMatt Jacob 		case SMS_CONTROL_MODE_PAGE:
1488d7b838eSMatt Jacob 		case SMS_ALL_PAGES_PAGE:
1498d7b838eSMatt Jacob 			break;
1508d7b838eSMatt Jacob 		default:
1518d7b838eSMatt Jacob 			vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0);
1528d7b838eSMatt Jacob 			TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
1538d7b838eSMatt Jacob 			return;
1548d7b838eSMatt Jacob 		}
1558d7b838eSMatt Jacob 		memset(junk, 0, sizeof (junk));
1568d7b838eSMatt Jacob 		if (cdb[1] & SMS_DBD) {
1578d7b838eSMatt Jacob 			ptr = &junk[4];
1588d7b838eSMatt Jacob 		} else {
1598d7b838eSMatt Jacob 			ptr = junk;
1608d7b838eSMatt Jacob 			ptr[3] = 8;
1618d7b838eSMatt Jacob 			ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff;
1628d7b838eSMatt Jacob 			ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff;
1638d7b838eSMatt Jacob 			ptr[6] = ((1 << DISK_SHIFT) >>  8) & 0xff;
1648d7b838eSMatt Jacob 			ptr[7] = ((1 << DISK_SHIFT)) & 0xff;
1658d7b838eSMatt Jacob 
1668d7b838eSMatt Jacob 			ptr[8] = (DISK_NBLKS >> 24) & 0xff;
1678d7b838eSMatt Jacob 			ptr[9] = (DISK_NBLKS >> 16) & 0xff;
1688d7b838eSMatt Jacob 			ptr[10] = (DISK_NBLKS >> 8) & 0xff;
1698d7b838eSMatt Jacob 			ptr[11] = DISK_NBLKS & 0xff;
1708d7b838eSMatt Jacob 			ptr += 12;
1718d7b838eSMatt Jacob 		}
1728d7b838eSMatt Jacob 
1738d7b838eSMatt Jacob 		if (page == SMS_ALL_PAGES_PAGE || page == SMS_FORMAT_DEVICE_PAGE) {
1748d7b838eSMatt Jacob 			ptr[0] = SMS_FORMAT_DEVICE_PAGE;
1758d7b838eSMatt Jacob 			ptr[1] = 24;
1768d7b838eSMatt Jacob 			if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) {
1778d7b838eSMatt Jacob 				/* tracks per zone */
1788d7b838eSMatt Jacob 				/* ptr[2] = 0; */
1798d7b838eSMatt Jacob 				/* ptr[3] = 0; */
1808d7b838eSMatt Jacob 				/* alternate sectors per zone */
1818d7b838eSMatt Jacob 				/* ptr[4] = 0; */
1828d7b838eSMatt Jacob 				/* ptr[5] = 0; */
1838d7b838eSMatt Jacob 				/* alternate tracks per zone */
1848d7b838eSMatt Jacob 				/* ptr[6] = 0; */
1858d7b838eSMatt Jacob 				/* ptr[7] = 0; */
1868d7b838eSMatt Jacob 				/* alternate tracks per logical unit */
1878d7b838eSMatt Jacob 				/* ptr[8] = 0; */
1888d7b838eSMatt Jacob 				/* ptr[9] = 0; */
1898d7b838eSMatt Jacob 				/* sectors per track */
1908d7b838eSMatt Jacob 				ptr[10] = (PSEUDO_SPT >> 8) & 0xff;
1918d7b838eSMatt Jacob 				ptr[11] = PSEUDO_SPT & 0xff;
1928d7b838eSMatt Jacob 				/* data bytes per physical sector */
1938d7b838eSMatt Jacob 				ptr[12] = ((1 << DISK_SHIFT) >> 8) & 0xff;
1948d7b838eSMatt Jacob 				ptr[13] = (1 << DISK_SHIFT) & 0xff;
1958d7b838eSMatt Jacob 				/* interleave */
1968d7b838eSMatt Jacob 				/* ptr[14] = 0; */
1978d7b838eSMatt Jacob 				/* ptr[15] = 1; */
1988d7b838eSMatt Jacob 				/* track skew factor */
1998d7b838eSMatt Jacob 				/* ptr[16] = 0; */
2008d7b838eSMatt Jacob 				/* ptr[17] = 0; */
2018d7b838eSMatt Jacob 				/* cylinder skew factor */
2028d7b838eSMatt Jacob 				/* ptr[18] = 0; */
2038d7b838eSMatt Jacob 				/* ptr[19] = 0; */
2048d7b838eSMatt Jacob 				/* SSRC, HSEC, RMB, SURF */
2058d7b838eSMatt Jacob 			}
2068d7b838eSMatt Jacob 			ptr += 26;
2078d7b838eSMatt Jacob 		}
2088d7b838eSMatt Jacob 
2098d7b838eSMatt Jacob 		if (page == SMS_ALL_PAGES_PAGE || page == SMS_GEOMETRY_PAGE) {
2108d7b838eSMatt Jacob 			ptr[0] = SMS_GEOMETRY_PAGE;
2118d7b838eSMatt Jacob 			ptr[1] = 24;
2128d7b838eSMatt Jacob 			if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) {
2138d7b838eSMatt Jacob 				uint32_t cyl = (DISK_NBLKS + ((PSEUDO_SPC - 1))) / PSEUDO_SPC;
2148d7b838eSMatt Jacob 				/* number of cylinders */
2158d7b838eSMatt Jacob 				ptr[2] = (cyl >> 24) & 0xff;
2168d7b838eSMatt Jacob 				ptr[3] = (cyl >> 16) & 0xff;
2178d7b838eSMatt Jacob 				ptr[4] = cyl & 0xff;
2188d7b838eSMatt Jacob 				/* number of heads */
2198d7b838eSMatt Jacob 				ptr[5] = PSEUDO_HDS;
2208d7b838eSMatt Jacob 				/* starting cylinder- write precompensation */
2218d7b838eSMatt Jacob 				/* ptr[6] = 0; */
2228d7b838eSMatt Jacob 				/* ptr[7] = 0; */
2238d7b838eSMatt Jacob 				/* ptr[8] = 0; */
2248d7b838eSMatt Jacob 				/* starting cylinder- reduced write current */
2258d7b838eSMatt Jacob 				/* ptr[9] = 0; */
2268d7b838eSMatt Jacob 				/* ptr[10] = 0; */
2278d7b838eSMatt Jacob 				/* ptr[11] = 0; */
2288d7b838eSMatt Jacob 				/* drive step rate */
2298d7b838eSMatt Jacob 				/* ptr[12] = 0; */
2308d7b838eSMatt Jacob 				/* ptr[13] = 0; */
2318d7b838eSMatt Jacob 				/* landing zone cylinder */
2328d7b838eSMatt Jacob 				/* ptr[14] = 0; */
2338d7b838eSMatt Jacob 				/* ptr[15] = 0; */
2348d7b838eSMatt Jacob 				/* ptr[16] = 0; */
2358d7b838eSMatt Jacob 				/* RPL */
2368d7b838eSMatt Jacob 				/* ptr[17] = 0; */
2378d7b838eSMatt Jacob 				/* rotational offset */
2388d7b838eSMatt Jacob 				/* ptr[18] = 0; */
2398d7b838eSMatt Jacob 				/* medium rotation rate -  7200 RPM */
2408d7b838eSMatt Jacob 				ptr[20] = 0x1c;
2418d7b838eSMatt Jacob 				ptr[21] = 0x20;
2428d7b838eSMatt Jacob 			}
2438d7b838eSMatt Jacob 			ptr += 26;
2448d7b838eSMatt Jacob 		}
2458d7b838eSMatt Jacob 
2468d7b838eSMatt Jacob 		if (page == SMS_ALL_PAGES_PAGE || page == SMS_CACHE_PAGE) {
2478d7b838eSMatt Jacob 			ptr[0] = SMS_CACHE_PAGE;
2488d7b838eSMatt Jacob 			ptr[1] = 18;
2498d7b838eSMatt Jacob 			ptr[2] = 1 << 2;
2508d7b838eSMatt Jacob 			ptr += 20;
2518d7b838eSMatt Jacob 		}
2528d7b838eSMatt Jacob 
2538d7b838eSMatt Jacob 		if (page == SMS_ALL_PAGES_PAGE || page == SMS_CONTROL_MODE_PAGE) {
2548d7b838eSMatt Jacob 			ptr[0] = SMS_CONTROL_MODE_PAGE;
2558d7b838eSMatt Jacob 			ptr[1] = 10;
2568d7b838eSMatt Jacob 			if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) {
2578d7b838eSMatt Jacob 				ptr[3] = 1 << 4; /* unrestricted reordering allowed */
2588d7b838eSMatt Jacob 				ptr[8] = 0x75;   /* 30000 ms */
2598d7b838eSMatt Jacob 				ptr[9] = 0x30;
2608d7b838eSMatt Jacob 			}
2618d7b838eSMatt Jacob 			ptr += 12;
2628d7b838eSMatt Jacob 		}
2638d7b838eSMatt Jacob 		nbyte = (char *)ptr - &junk[0];
2648d7b838eSMatt Jacob 		ptr[0] = nbyte - 4;
2658d7b838eSMatt Jacob 
2668d7b838eSMatt Jacob 		if (cdb[0] == MODE_SENSE) {
2678d7b838eSMatt Jacob 			data_len = min(cdb[4], csio->dxfer_len);
2688d7b838eSMatt Jacob 		} else {
2698d7b838eSMatt Jacob 			uint16_t tw = (cdb[7] << 8) | cdb[8];
2708d7b838eSMatt Jacob 			data_len = min(tw, csio->dxfer_len);
2718d7b838eSMatt Jacob 		}
2728d7b838eSMatt Jacob 		data_len = min(data_len, nbyte);
2738d7b838eSMatt Jacob 		if (data_len) {
2748d7b838eSMatt Jacob 			memcpy(csio->data_ptr, junk, data_len);
2758d7b838eSMatt Jacob 		}
2768d7b838eSMatt Jacob 		csio->resid = csio->dxfer_len - data_len;
2778d7b838eSMatt Jacob 		break;
2788d7b838eSMatt Jacob 	}
2798d7b838eSMatt Jacob 	case READ_6:
2808d7b838eSMatt Jacob 	case READ_10:
2818d7b838eSMatt Jacob 	case READ_12:
2828d7b838eSMatt Jacob 	case READ_16:
2838d7b838eSMatt Jacob 	case WRITE_6:
2848d7b838eSMatt Jacob 	case WRITE_10:
2858d7b838eSMatt Jacob 	case WRITE_12:
2868d7b838eSMatt Jacob 	case WRITE_16:
2878d7b838eSMatt Jacob 		if (vhba_rwparm(cdb, &off, &data_len, DISK_NBLKS, DISK_SHIFT)) {
2888d7b838eSMatt Jacob 			vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0);
2898d7b838eSMatt Jacob 			break;
2908d7b838eSMatt Jacob 		}
2918d7b838eSMatt Jacob 		if (data_len) {
2928d7b838eSMatt Jacob 			if ((cdb[0] & 0xf) == 8) {
2938d7b838eSMatt Jacob 				memcpy(csio->data_ptr, &vhbas->disk[off], data_len);
2948d7b838eSMatt Jacob 			} else {
2958d7b838eSMatt Jacob 				memcpy(&vhbas->disk[off], csio->data_ptr, data_len);
2968d7b838eSMatt Jacob 			}
2978d7b838eSMatt Jacob 			csio->resid = csio->dxfer_len - data_len;
2988d7b838eSMatt Jacob 		} else {
2998d7b838eSMatt Jacob 			csio->resid = csio->dxfer_len;
3008d7b838eSMatt Jacob 		}
3018d7b838eSMatt Jacob 		break;
3028d7b838eSMatt Jacob 
3038d7b838eSMatt Jacob 	case READ_CAPACITY:
3048d7b838eSMatt Jacob 		if (cdb[2] || cdb[3] || cdb[4] || cdb[5]) {
3058d7b838eSMatt Jacob 			vhba_fill_sense(csio, SSD_KEY_UNIT_ATTENTION, 0x24, 0x0);
3068d7b838eSMatt Jacob 			break;
3078d7b838eSMatt Jacob 		}
3088d7b838eSMatt Jacob 		if (cdb[8] & 0x1) { /* PMI */
3098d7b838eSMatt Jacob 			csio->data_ptr[0] = 0xff;
3108d7b838eSMatt Jacob 			csio->data_ptr[1] = 0xff;
3118d7b838eSMatt Jacob 			csio->data_ptr[2] = 0xff;
3128d7b838eSMatt Jacob 			csio->data_ptr[3] = 0xff;
3138d7b838eSMatt Jacob 		} else {
3148d7b838eSMatt Jacob 			uint64_t last_blk = DISK_NBLKS - 1;
3158d7b838eSMatt Jacob 			if (last_blk < 0xffffffffULL) {
3168d7b838eSMatt Jacob 			    csio->data_ptr[0] = (last_blk >> 24) & 0xff;
3178d7b838eSMatt Jacob 			    csio->data_ptr[1] = (last_blk >> 16) & 0xff;
3188d7b838eSMatt Jacob 			    csio->data_ptr[2] = (last_blk >>  8) & 0xff;
3198d7b838eSMatt Jacob 			    csio->data_ptr[3] = (last_blk) & 0xff;
3208d7b838eSMatt Jacob 			} else {
3218d7b838eSMatt Jacob 			    csio->data_ptr[0] = 0xff;
3228d7b838eSMatt Jacob 			    csio->data_ptr[1] = 0xff;
3238d7b838eSMatt Jacob 			    csio->data_ptr[2] = 0xff;
3248d7b838eSMatt Jacob 			    csio->data_ptr[3] = 0xff;
3258d7b838eSMatt Jacob 			}
3268d7b838eSMatt Jacob 		}
3278d7b838eSMatt Jacob 		csio->data_ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff;
3288d7b838eSMatt Jacob 		csio->data_ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff;
3298d7b838eSMatt Jacob 		csio->data_ptr[6] = ((1 << DISK_SHIFT) >>  8) & 0xff;
3308d7b838eSMatt Jacob 		csio->data_ptr[7] = ((1 << DISK_SHIFT)) & 0xff;
3318d7b838eSMatt Jacob 		break;
3328d7b838eSMatt Jacob 	default:
3338d7b838eSMatt Jacob 		vhba_default_cmd(csio, MAX_LUN, NULL);
3348d7b838eSMatt Jacob 		break;
3358d7b838eSMatt Jacob 	}
3368d7b838eSMatt Jacob 	if (csio->scsi_status != SCSI_STATUS_OK) {
3378d7b838eSMatt Jacob 		camstatus = CAM_SCSI_STATUS_ERROR;
3388d7b838eSMatt Jacob 		if (csio->scsi_status == SCSI_STATUS_CHECK_COND) {
3398d7b838eSMatt Jacob 			camstatus |= CAM_AUTOSNS_VALID;
3408d7b838eSMatt Jacob 		}
3418d7b838eSMatt Jacob 	} else {
3428d7b838eSMatt Jacob 		csio->scsi_status = SCSI_STATUS_OK;
3438d7b838eSMatt Jacob 		camstatus = CAM_REQ_CMP;
3448d7b838eSMatt Jacob 	}
3458d7b838eSMatt Jacob 	vhba_set_status(&csio->ccb_h, camstatus);
3468d7b838eSMatt Jacob 	TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe);
3478d7b838eSMatt Jacob }
3488d7b838eSMatt Jacob DEV_MODULE(vhba_faulty, vhba_modprobe, NULL);
349