From owner-svn-src-head@FreeBSD.ORG Tue Jun 8 22:26:48 2010 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7946010656C4; Tue, 8 Jun 2010 22:26:48 +0000 (UTC) (envelope-from mjacob@FreeBSD.org) Received: from svn.freebsd.org (unknown [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 665038FC1B; Tue, 8 Jun 2010 22:26:48 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o58MQmWx032022; Tue, 8 Jun 2010 22:26:48 GMT (envelope-from mjacob@svn.freebsd.org) Received: (from mjacob@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o58MQmbk032012; Tue, 8 Jun 2010 22:26:48 GMT (envelope-from mjacob@svn.freebsd.org) Message-Id: <201006082226.o58MQmbk032012@svn.freebsd.org> From: Matt Jacob Date: Tue, 8 Jun 2010 22:26:48 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r208926 - in head/tools/tools/vhba: . faulty lots medium rptluns simple X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Jun 2010 22:26:48 -0000 Author: mjacob Date: Tue Jun 8 22:26:47 2010 New Revision: 208926 URL: http://svn.freebsd.org/changeset/base/208926 Log: Add the VHBA package. It is here in tools because it's really a testbed. Sponsored by: Panasas MFC after: 1 month Added: head/tools/tools/vhba/ head/tools/tools/vhba/Makefile (contents, props changed) head/tools/tools/vhba/README (contents, props changed) head/tools/tools/vhba/faulty/ head/tools/tools/vhba/faulty/Makefile (contents, props changed) head/tools/tools/vhba/faulty/vhba_faulty.c (contents, props changed) head/tools/tools/vhba/lots/ head/tools/tools/vhba/lots/Makefile (contents, props changed) head/tools/tools/vhba/lots/vhba_lots.c (contents, props changed) head/tools/tools/vhba/medium/ head/tools/tools/vhba/medium/Makefile (contents, props changed) head/tools/tools/vhba/medium/vhba_medium.c (contents, props changed) head/tools/tools/vhba/opt_cam.h (contents, props changed) head/tools/tools/vhba/rptluns/ head/tools/tools/vhba/rptluns/Makefile (contents, props changed) head/tools/tools/vhba/rptluns/vhba_rptluns.c (contents, props changed) head/tools/tools/vhba/simple/ head/tools/tools/vhba/simple/Makefile (contents, props changed) head/tools/tools/vhba/simple/vhba_simple.c (contents, props changed) head/tools/tools/vhba/vhba.c (contents, props changed) head/tools/tools/vhba/vhba.h (contents, props changed) Added: head/tools/tools/vhba/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/Makefile Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,29 @@ +# $FreeBSD$ +# +# Copyright (c) 2010 by Panasas Inc +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice immediately at the beginning of the file, without modification, +# this list of conditions, and the following disclaimer. +# 2. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +SUBDIR= simple medium lots faulty rptluns + +.include Added: head/tools/tools/vhba/README ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/README Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,16 @@ +$FreeBSD$ +Tue Jun 8 15:02:02 PDT 2010 + +This packages is a testbed for a number of purposes and consists +of two pieces. + +The first piece is a simple SIM driver for FreeBSD. It provides +*just enough* framework to be useful, plus some nominally common +code responses for code sharing purposes. + +The second piece(s) are underlying implementations which make various +virtual devices implemented under the VHBA itself. The current ones +are pretty much used to stress and test the FreeBSD CAM framework +itself- this is why this is in the tool directory. + +Clearly other connections and possibilities exist as well. Added: head/tools/tools/vhba/faulty/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/faulty/Makefile Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,7 @@ +# $FreeBSD$ +KMOD= vfaulty +SRCS= vhba_faulty.c vhba.c +CFLAGS += -I${.CURDIR}/.. -DVHBA_MOD=\"vfaulty\" +VPATH= ${.CURDIR}/.. + +.include Added: head/tools/tools/vhba/faulty/vhba_faulty.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/faulty/vhba_faulty.c Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,349 @@ +/*- + * Copyright (c) 2010 by Panasas, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* + * "Faulty" Device. Victimize random commands with a Selection Timeout. + */ +#include "vhba.h" + +#define MAX_TGT VHBA_MAXTGT +#define MAX_LUN 4 + +#define DISK_SIZE 32 +#define DISK_SHIFT 9 +#define DISK_NBLKS ((DISK_SIZE << 20) >> DISK_SHIFT) +#define PSEUDO_SPT 64 +#define PSEUDO_HDS 64 +#define PSEUDO_SPC (PSEUDO_SPT * PSEUDO_HDS) + +typedef struct { + vhba_softc_t * vhba; + uint8_t * disk; + size_t disk_size; + uint32_t ctr; + uint32_t dead; + struct task qt; +} faulty_t; + +static void vhba_task(void *, int); +static void faulty_act(faulty_t *, struct ccb_scsiio *); + +void +vhba_init(vhba_softc_t *vhba) +{ + static faulty_t vhbastatic; + vhbastatic.vhba = vhba; + vhbastatic.disk_size = DISK_SIZE << 20; + vhbastatic.disk = malloc(vhbastatic.disk_size, M_DEVBUF, M_WAITOK|M_ZERO); + vhba->private = &vhbastatic; + vhbastatic.ctr = (arc4random() & 0xffff) + 1; + TASK_INIT(&vhbastatic.qt, 0, vhba_task, &vhbastatic); +} + + +void +vhba_fini(vhba_softc_t *vhba) +{ + faulty_t *vhbas = vhba->private; + vhba->private = NULL; + free(vhbas->disk, M_DEVBUF); +} + +void +vhba_kick(vhba_softc_t *vhba) +{ + faulty_t *vhbas = vhba->private; + taskqueue_enqueue(taskqueue_swi, &vhbas->qt); +} + +static void +vhba_task(void *arg, int pending) +{ + faulty_t *vhbas = arg; + struct ccb_hdr *ccbh; + + mtx_lock(&vhbas->vhba->lock); + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->actv)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->actv, ccbh, sim_links.tqe); + faulty_act(vhbas, (struct ccb_scsiio *)ccbh); + if (--vhbas->ctr == 0) { + vhbas->dead = 1; + vhbas->ctr = (arc4random() & 0xff) + 1; + } + } + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe); + xpt_done((union ccb *)ccbh); + } + mtx_unlock(&vhbas->vhba->lock); +} + +static void +faulty_act(faulty_t *vhbas, struct ccb_scsiio *csio) +{ + char junk[128]; + cam_status camstatus; + uint8_t *cdb, *ptr, status; + uint32_t data_len; + uint64_t off; + + data_len = 0; + status = SCSI_STATUS_OK; + + memset(&csio->sense_data, 0, sizeof (csio->sense_data)); + cdb = csio->cdb_io.cdb_bytes; + + if (csio->ccb_h.target_id >= MAX_TGT) { + vhba_set_status(&csio->ccb_h, CAM_SEL_TIMEOUT); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + if (vhbas->dead) { + vhbas->dead = 0; + vhba_set_status(&csio->ccb_h, CAM_SEL_TIMEOUT); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + if (csio->ccb_h.target_lun >= MAX_LUN && cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) { + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x25, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + + switch (cdb[0]) { + case MODE_SENSE: + case MODE_SENSE_10: + { + unsigned int nbyte; + uint8_t page = cdb[2] & SMS_PAGE_CODE; + uint8_t pgctl = cdb[2] & SMS_PAGE_CTRL_MASK; + + switch (page) { + case SMS_FORMAT_DEVICE_PAGE: + case SMS_GEOMETRY_PAGE: + case SMS_CACHE_PAGE: + case SMS_CONTROL_MODE_PAGE: + case SMS_ALL_PAGES_PAGE: + break; + default: + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + memset(junk, 0, sizeof (junk)); + if (cdb[1] & SMS_DBD) { + ptr = &junk[4]; + } else { + ptr = junk; + ptr[3] = 8; + ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff; + ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff; + ptr[6] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[7] = ((1 << DISK_SHIFT)) & 0xff; + + ptr[8] = (DISK_NBLKS >> 24) & 0xff; + ptr[9] = (DISK_NBLKS >> 16) & 0xff; + ptr[10] = (DISK_NBLKS >> 8) & 0xff; + ptr[11] = DISK_NBLKS & 0xff; + ptr += 12; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_FORMAT_DEVICE_PAGE) { + ptr[0] = SMS_FORMAT_DEVICE_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + /* tracks per zone */ + /* ptr[2] = 0; */ + /* ptr[3] = 0; */ + /* alternate sectors per zone */ + /* ptr[4] = 0; */ + /* ptr[5] = 0; */ + /* alternate tracks per zone */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* alternate tracks per logical unit */ + /* ptr[8] = 0; */ + /* ptr[9] = 0; */ + /* sectors per track */ + ptr[10] = (PSEUDO_SPT >> 8) & 0xff; + ptr[11] = PSEUDO_SPT & 0xff; + /* data bytes per physical sector */ + ptr[12] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[13] = (1 << DISK_SHIFT) & 0xff; + /* interleave */ + /* ptr[14] = 0; */ + /* ptr[15] = 1; */ + /* track skew factor */ + /* ptr[16] = 0; */ + /* ptr[17] = 0; */ + /* cylinder skew factor */ + /* ptr[18] = 0; */ + /* ptr[19] = 0; */ + /* SSRC, HSEC, RMB, SURF */ + } + ptr += 26; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_GEOMETRY_PAGE) { + ptr[0] = SMS_GEOMETRY_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + uint32_t cyl = (DISK_NBLKS + ((PSEUDO_SPC - 1))) / PSEUDO_SPC; + /* number of cylinders */ + ptr[2] = (cyl >> 24) & 0xff; + ptr[3] = (cyl >> 16) & 0xff; + ptr[4] = cyl & 0xff; + /* number of heads */ + ptr[5] = PSEUDO_HDS; + /* starting cylinder- write precompensation */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* ptr[8] = 0; */ + /* starting cylinder- reduced write current */ + /* ptr[9] = 0; */ + /* ptr[10] = 0; */ + /* ptr[11] = 0; */ + /* drive step rate */ + /* ptr[12] = 0; */ + /* ptr[13] = 0; */ + /* landing zone cylinder */ + /* ptr[14] = 0; */ + /* ptr[15] = 0; */ + /* ptr[16] = 0; */ + /* RPL */ + /* ptr[17] = 0; */ + /* rotational offset */ + /* ptr[18] = 0; */ + /* medium rotation rate - 7200 RPM */ + ptr[20] = 0x1c; + ptr[21] = 0x20; + } + ptr += 26; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_CACHE_PAGE) { + ptr[0] = SMS_CACHE_PAGE; + ptr[1] = 18; + ptr[2] = 1 << 2; + ptr += 20; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_CONTROL_MODE_PAGE) { + ptr[0] = SMS_CONTROL_MODE_PAGE; + ptr[1] = 10; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + ptr[3] = 1 << 4; /* unrestricted reordering allowed */ + ptr[8] = 0x75; /* 30000 ms */ + ptr[9] = 0x30; + } + ptr += 12; + } + nbyte = (char *)ptr - &junk[0]; + ptr[0] = nbyte - 4; + + if (cdb[0] == MODE_SENSE) { + data_len = min(cdb[4], csio->dxfer_len); + } else { + uint16_t tw = (cdb[7] << 8) | cdb[8]; + data_len = min(tw, csio->dxfer_len); + } + data_len = min(data_len, nbyte); + if (data_len) { + memcpy(csio->data_ptr, junk, data_len); + } + csio->resid = csio->dxfer_len - data_len; + break; + } + case READ_6: + case READ_10: + case READ_12: + case READ_16: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_16: + if (vhba_rwparm(cdb, &off, &data_len, DISK_NBLKS, DISK_SHIFT)) { + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0); + break; + } + if (data_len) { + if ((cdb[0] & 0xf) == 8) { + memcpy(csio->data_ptr, &vhbas->disk[off], data_len); + } else { + memcpy(&vhbas->disk[off], csio->data_ptr, data_len); + } + csio->resid = csio->dxfer_len - data_len; + } else { + csio->resid = csio->dxfer_len; + } + break; + + case READ_CAPACITY: + if (cdb[2] || cdb[3] || cdb[4] || cdb[5]) { + vhba_fill_sense(csio, SSD_KEY_UNIT_ATTENTION, 0x24, 0x0); + break; + } + if (cdb[8] & 0x1) { /* PMI */ + csio->data_ptr[0] = 0xff; + csio->data_ptr[1] = 0xff; + csio->data_ptr[2] = 0xff; + csio->data_ptr[3] = 0xff; + } else { + uint64_t last_blk = DISK_NBLKS - 1; + if (last_blk < 0xffffffffULL) { + csio->data_ptr[0] = (last_blk >> 24) & 0xff; + csio->data_ptr[1] = (last_blk >> 16) & 0xff; + csio->data_ptr[2] = (last_blk >> 8) & 0xff; + csio->data_ptr[3] = (last_blk) & 0xff; + } else { + csio->data_ptr[0] = 0xff; + csio->data_ptr[1] = 0xff; + csio->data_ptr[2] = 0xff; + csio->data_ptr[3] = 0xff; + } + } + csio->data_ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff; + csio->data_ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff; + csio->data_ptr[6] = ((1 << DISK_SHIFT) >> 8) & 0xff; + csio->data_ptr[7] = ((1 << DISK_SHIFT)) & 0xff; + break; + default: + vhba_default_cmd(csio, MAX_LUN, NULL); + break; + } + if (csio->scsi_status != SCSI_STATUS_OK) { + camstatus = CAM_SCSI_STATUS_ERROR; + if (csio->scsi_status == SCSI_STATUS_CHECK_COND) { + camstatus |= CAM_AUTOSNS_VALID; + } + } else { + csio->scsi_status = SCSI_STATUS_OK; + camstatus = CAM_REQ_CMP; + } + vhba_set_status(&csio->ccb_h, camstatus); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); +} +DEV_MODULE(vhba_faulty, vhba_modprobe, NULL); Added: head/tools/tools/vhba/lots/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/lots/Makefile Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,7 @@ +# $FreeBSD$ +KMOD= vlots +SRCS= vhba_lots.c vhba.c +CFLAGS += -I${.CURDIR}/.. -DVHBA_MOD=\"vlots\" +VPATH= ${.CURDIR}/.. + +.include Added: head/tools/tools/vhba/lots/vhba_lots.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/lots/vhba_lots.c Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,335 @@ +/*- + * Copyright (c) 2010 by Panasas, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* + * VHBA device that just reate boatloads of devices. + */ +#include "vhba.h" + +#define MAX_TGT VHBA_MAXTGT +#define MAX_LUN 32 + +#define DISK_SIZE 32 +#define DISK_SHIFT 9 +#define DISK_NBLKS ((DISK_SIZE << 20) >> DISK_SHIFT) +#define PSEUDO_SPT 64 +#define PSEUDO_HDS 64 +#define PSEUDO_SPC (PSEUDO_SPT * PSEUDO_HDS) + +typedef struct { + vhba_softc_t * vhba; + uint8_t * disk; + size_t disk_size; + struct task qt; +} vhbalots_t; + +static void vhba_task(void *, int); +static void vhbalots_act(vhbalots_t *, struct ccb_scsiio *); + +void +vhba_init(vhba_softc_t *vhba) +{ + static vhbalots_t vhbas; + vhbas.vhba = vhba; + vhbas.disk_size = DISK_SIZE << 20; + vhbas.disk = malloc(vhbas.disk_size, M_DEVBUF, M_WAITOK|M_ZERO); + vhba->private = &vhbas; + TASK_INIT(&vhbas.qt, 0, vhba_task, &vhbas); +} + + +void +vhba_fini(vhba_softc_t *vhba) +{ + vhbalots_t *vhbas = vhba->private; + vhba->private = NULL; + free(vhbas->disk, M_DEVBUF); +} + +void +vhba_kick(vhba_softc_t *vhba) +{ + vhbalots_t *vhbas = vhba->private; + taskqueue_enqueue(taskqueue_swi, &vhbas->qt); +} + +static void +vhba_task(void *arg, int pending) +{ + vhbalots_t *vhbas = arg; + struct ccb_hdr *ccbh; + + mtx_lock(&vhbas->vhba->lock); + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->actv)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->actv, ccbh, sim_links.tqe); + vhbalots_act(vhbas, (struct ccb_scsiio *)ccbh); + } + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe); + xpt_done((union ccb *)ccbh); + } + mtx_unlock(&vhbas->vhba->lock); +} + +static void +vhbalots_act(vhbalots_t *vhbas, struct ccb_scsiio *csio) +{ + char junk[128]; + uint8_t *cdb, *ptr, status; + uint32_t data_len; + uint64_t off; + + data_len = 0; + status = SCSI_STATUS_OK; + + memset(&csio->sense_data, 0, sizeof (csio->sense_data)); + cdb = csio->cdb_io.cdb_bytes; + + if (csio->ccb_h.target_id >= MAX_TGT) { + csio->ccb_h.status = CAM_SEL_TIMEOUT; + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + if (csio->ccb_h.target_lun >= MAX_LUN && cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) { + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x25, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + + switch (cdb[0]) { + case MODE_SENSE: + case MODE_SENSE_10: + { + unsigned int nbyte; + uint8_t page = cdb[2] & SMS_PAGE_CODE; + uint8_t pgctl = cdb[2] & SMS_PAGE_CTRL_MASK; + + switch (page) { + case SMS_FORMAT_DEVICE_PAGE: + case SMS_GEOMETRY_PAGE: + case SMS_CACHE_PAGE: + case SMS_CONTROL_MODE_PAGE: + case SMS_ALL_PAGES_PAGE: + break; + default: + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + memset(junk, 0, sizeof (junk)); + if (cdb[1] & SMS_DBD) { + ptr = &junk[4]; + } else { + ptr = junk; + ptr[3] = 8; + ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff; + ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff; + ptr[6] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[7] = ((1 << DISK_SHIFT)) & 0xff; + + ptr[8] = (DISK_NBLKS >> 24) & 0xff; + ptr[9] = (DISK_NBLKS >> 16) & 0xff; + ptr[10] = (DISK_NBLKS >> 8) & 0xff; + ptr[11] = DISK_NBLKS & 0xff; + ptr += 12; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_FORMAT_DEVICE_PAGE) { + ptr[0] = SMS_FORMAT_DEVICE_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + /* tracks per zone */ + /* ptr[2] = 0; */ + /* ptr[3] = 0; */ + /* alternate sectors per zone */ + /* ptr[4] = 0; */ + /* ptr[5] = 0; */ + /* alternate tracks per zone */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* alternate tracks per logical unit */ + /* ptr[8] = 0; */ + /* ptr[9] = 0; */ + /* sectors per track */ + ptr[10] = (PSEUDO_SPT >> 8) & 0xff; + ptr[11] = PSEUDO_SPT & 0xff; + /* data bytes per physical sector */ + ptr[12] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[13] = (1 << DISK_SHIFT) & 0xff; + /* interleave */ + /* ptr[14] = 0; */ + /* ptr[15] = 1; */ + /* track skew factor */ + /* ptr[16] = 0; */ + /* ptr[17] = 0; */ + /* cylinder skew factor */ + /* ptr[18] = 0; */ + /* ptr[19] = 0; */ + /* SSRC, HSEC, RMB, SURF */ + } + ptr += 26; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_GEOMETRY_PAGE) { + ptr[0] = SMS_GEOMETRY_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + uint32_t cyl = (DISK_NBLKS + ((PSEUDO_SPC - 1))) / PSEUDO_SPC; + /* number of cylinders */ + ptr[2] = (cyl >> 24) & 0xff; + ptr[3] = (cyl >> 16) & 0xff; + ptr[4] = cyl & 0xff; + /* number of heads */ + ptr[5] = PSEUDO_HDS; + /* starting cylinder- write precompensation */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* ptr[8] = 0; */ + /* starting cylinder- reduced write current */ + /* ptr[9] = 0; */ + /* ptr[10] = 0; */ + /* ptr[11] = 0; */ + /* drive step rate */ + /* ptr[12] = 0; */ + /* ptr[13] = 0; */ + /* landing zone cylinder */ + /* ptr[14] = 0; */ + /* ptr[15] = 0; */ + /* ptr[16] = 0; */ + /* RPL */ + /* ptr[17] = 0; */ + /* rotational offset */ + /* ptr[18] = 0; */ + /* medium rotation rate - 7200 RPM */ + ptr[20] = 0x1c; + ptr[21] = 0x20; + } + ptr += 26; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_CACHE_PAGE) { + ptr[0] = SMS_CACHE_PAGE; + ptr[1] = 18; + ptr[2] = 1 << 2; + ptr += 20; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_CONTROL_MODE_PAGE) { + ptr[0] = SMS_CONTROL_MODE_PAGE; + ptr[1] = 10; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + ptr[3] = 1 << 4; /* unrestricted reordering allowed */ + ptr[8] = 0x75; /* 30000 ms */ + ptr[9] = 0x30; + } + ptr += 12; + } + nbyte = (char *)ptr - &junk[0]; + ptr[0] = nbyte - 4; + + if (cdb[0] == MODE_SENSE) { + data_len = min(cdb[4], csio->dxfer_len); + } else { + uint16_t tw = (cdb[7] << 8) | cdb[8]; + data_len = min(tw, csio->dxfer_len); + } + data_len = min(data_len, nbyte); + if (data_len) { + memcpy(csio->data_ptr, junk, data_len); + } + csio->resid = csio->dxfer_len - data_len; + break; + } + case READ_6: + case READ_10: + case READ_12: + case READ_16: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_16: + if (vhba_rwparm(cdb, &off, &data_len, DISK_NBLKS, DISK_SHIFT)) { + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0); + break; + } + if (data_len) { + if ((cdb[0] & 0xf) == 8) { + memcpy(csio->data_ptr, &vhbas->disk[off], data_len); + } else { + memcpy(&vhbas->disk[off], csio->data_ptr, data_len); + } + csio->resid = csio->dxfer_len - data_len; + } else { + csio->resid = csio->dxfer_len; + } + break; + + case READ_CAPACITY: + if (cdb[2] || cdb[3] || cdb[4] || cdb[5]) { + vhba_fill_sense(csio, SSD_KEY_UNIT_ATTENTION, 0x24, 0x0); + break; + } + if (cdb[8] & 0x1) { /* PMI */ + csio->data_ptr[0] = 0xff; + csio->data_ptr[1] = 0xff; + csio->data_ptr[2] = 0xff; + csio->data_ptr[3] = 0xff; + } else { + uint64_t last_blk = DISK_NBLKS - 1; + if (last_blk < 0xffffffffULL) { + csio->data_ptr[0] = (last_blk >> 24) & 0xff; + csio->data_ptr[1] = (last_blk >> 16) & 0xff; + csio->data_ptr[2] = (last_blk >> 8) & 0xff; + csio->data_ptr[3] = (last_blk) & 0xff; + } else { + csio->data_ptr[0] = 0xff; + csio->data_ptr[1] = 0xff; + csio->data_ptr[2] = 0xff; + csio->data_ptr[3] = 0xff; + } + } + csio->data_ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff; + csio->data_ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff; + csio->data_ptr[6] = ((1 << DISK_SHIFT) >> 8) & 0xff; + csio->data_ptr[7] = ((1 << DISK_SHIFT)) & 0xff; + break; + default: + vhba_default_cmd(csio, MAX_LUN, NULL); + break; + } + csio->ccb_h.status &= ~CAM_STATUS_MASK; + if (csio->scsi_status != SCSI_STATUS_OK) { + csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; + if (csio->scsi_status == SCSI_STATUS_CHECK_COND) { + csio->ccb_h.status |= CAM_AUTOSNS_VALID; + } + } else { + csio->scsi_status = SCSI_STATUS_OK; + csio->ccb_h.status |= CAM_REQ_CMP; + } + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); +} +DEV_MODULE(vhba_lots, vhba_modprobe, NULL); Added: head/tools/tools/vhba/medium/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/medium/Makefile Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,7 @@ +# $FreeBSD$ +KMOD= vmedium +SRCS= vhba_medium.c vhba.c +CFLAGS += -I${.CURDIR}/.. -DVHBA_MOD=\"vmedium\" +VPATH= ${.CURDIR}/.. + +.include Added: head/tools/tools/vhba/medium/vhba_medium.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/tools/vhba/medium/vhba_medium.c Tue Jun 8 22:26:47 2010 (r208926) @@ -0,0 +1,337 @@ +/*- + * Copyright (c) 2010 by Panasas, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice immediately at the beginning of the file, without modification, + * this list of conditions, and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* $FreeBSD$ */ +/* + * A VHBA device that has a medium number of device. + */ +#include "vhba.h" + +#define MAX_TGT 4 +#define MAX_LUN 10 + +#define DISK_SIZE 32 +#define DISK_SHIFT 9 +#define DISK_NBLKS ((DISK_SIZE << 20) >> DISK_SHIFT) +#define PSEUDO_SPT 64 +#define PSEUDO_HDS 64 +#define PSEUDO_SPC (PSEUDO_SPT * PSEUDO_HDS) + +typedef struct { + vhba_softc_t * vhba; + uint8_t * disk; + size_t disk_size; + struct task qt; +} vhbamedium_t; + +static void vhba_task(void *, int); +static void vhbamedium_act(vhbamedium_t *, struct ccb_scsiio *); + +void +vhba_init(vhba_softc_t *vhba) +{ + static vhbamedium_t vhbas; + vhbas.vhba = vhba; + vhbas.disk_size = DISK_SIZE << 20; + vhbas.disk = malloc(vhbas.disk_size, M_DEVBUF, M_WAITOK|M_ZERO); + vhba->private = &vhbas; + TASK_INIT(&vhbas.qt, 0, vhba_task, &vhbas); +} + + +void +vhba_fini(vhba_softc_t *vhba) +{ + vhbamedium_t *vhbas = vhba->private; + vhba->private = NULL; + free(vhbas->disk, M_DEVBUF); +} + +void +vhba_kick(vhba_softc_t *vhba) +{ + vhbamedium_t *vhbas = vhba->private; + taskqueue_enqueue(taskqueue_swi, &vhbas->qt); +} + +static void +vhba_task(void *arg, int pending) +{ + vhbamedium_t *vhbas = arg; + struct ccb_hdr *ccbh; + + mtx_lock(&vhbas->vhba->lock); + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->actv)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->actv, ccbh, sim_links.tqe); + vhbamedium_act(vhbas, (struct ccb_scsiio *)ccbh); + } + while ((ccbh = TAILQ_FIRST(&vhbas->vhba->done)) != NULL) { + TAILQ_REMOVE(&vhbas->vhba->done, ccbh, sim_links.tqe); + xpt_done((union ccb *)ccbh); + } + mtx_unlock(&vhbas->vhba->lock); +} + +static void +vhbamedium_act(vhbamedium_t *vhbas, struct ccb_scsiio *csio) +{ + char junk[128]; + uint8_t *cdb, *ptr, status; + uint32_t data_len; + uint64_t off; + + data_len = 0; + status = SCSI_STATUS_OK; + + memset(&csio->sense_data, 0, sizeof (csio->sense_data)); + cdb = csio->cdb_io.cdb_bytes; + + if (csio->ccb_h.target_id >= MAX_TGT) { + csio->ccb_h.status = CAM_SEL_TIMEOUT; + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + if (csio->ccb_h.target_lun >= MAX_LUN && cdb[0] != INQUIRY && cdb[0] != REPORT_LUNS && cdb[0] != REQUEST_SENSE) { + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x25, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + + switch (cdb[0]) { + case MODE_SENSE: + case MODE_SENSE_10: + { + unsigned int nbyte; + uint8_t page = cdb[2] & SMS_PAGE_CODE; + uint8_t pgctl = cdb[2] & SMS_PAGE_CTRL_MASK; + + switch (page) { + case SMS_FORMAT_DEVICE_PAGE: + case SMS_GEOMETRY_PAGE: + case SMS_CACHE_PAGE: + case SMS_CONTROL_MODE_PAGE: + case SMS_ALL_PAGES_PAGE: + break; + default: + vhba_fill_sense(csio, SSD_KEY_ILLEGAL_REQUEST, 0x24, 0x0); + TAILQ_INSERT_TAIL(&vhbas->vhba->done, &csio->ccb_h, sim_links.tqe); + return; + } + memset(junk, 0, sizeof (junk)); + if (cdb[1] & SMS_DBD) { + ptr = &junk[4]; + } else { + ptr = junk; + ptr[3] = 8; + ptr[4] = ((1 << DISK_SHIFT) >> 24) & 0xff; + ptr[5] = ((1 << DISK_SHIFT) >> 16) & 0xff; + ptr[6] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[7] = ((1 << DISK_SHIFT)) & 0xff; + + ptr[8] = (DISK_NBLKS >> 24) & 0xff; + ptr[9] = (DISK_NBLKS >> 16) & 0xff; + ptr[10] = (DISK_NBLKS >> 8) & 0xff; + ptr[11] = DISK_NBLKS & 0xff; + ptr += 12; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_FORMAT_DEVICE_PAGE) { + ptr[0] = SMS_FORMAT_DEVICE_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + /* tracks per zone */ + /* ptr[2] = 0; */ + /* ptr[3] = 0; */ + /* alternate sectors per zone */ + /* ptr[4] = 0; */ + /* ptr[5] = 0; */ + /* alternate tracks per zone */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* alternate tracks per logical unit */ + /* ptr[8] = 0; */ + /* ptr[9] = 0; */ + /* sectors per track */ + ptr[10] = (PSEUDO_SPT >> 8) & 0xff; + ptr[11] = PSEUDO_SPT & 0xff; + /* data bytes per physical sector */ + ptr[12] = ((1 << DISK_SHIFT) >> 8) & 0xff; + ptr[13] = (1 << DISK_SHIFT) & 0xff; + /* interleave */ + /* ptr[14] = 0; */ + /* ptr[15] = 1; */ + /* track skew factor */ + /* ptr[16] = 0; */ + /* ptr[17] = 0; */ + /* cylinder skew factor */ + /* ptr[18] = 0; */ + /* ptr[19] = 0; */ + /* SSRC, HSEC, RMB, SURF */ + } + ptr += 26; + } + + if (page == SMS_ALL_PAGES_PAGE || page == SMS_GEOMETRY_PAGE) { + ptr[0] = SMS_GEOMETRY_PAGE; + ptr[1] = 24; + if (pgctl != SMS_PAGE_CTRL_CHANGEABLE) { + uint32_t cyl = (DISK_NBLKS + ((PSEUDO_SPC - 1))) / PSEUDO_SPC; + /* number of cylinders */ + ptr[2] = (cyl >> 24) & 0xff; + ptr[3] = (cyl >> 16) & 0xff; + ptr[4] = cyl & 0xff; + /* number of heads */ + ptr[5] = PSEUDO_HDS; + /* starting cylinder- write precompensation */ + /* ptr[6] = 0; */ + /* ptr[7] = 0; */ + /* ptr[8] = 0; */ + /* starting cylinder- reduced write current */ + /* ptr[9] = 0; */ + /* ptr[10] = 0; */ + /* ptr[11] = 0; */ + /* drive step rate */ + /* ptr[12] = 0; */ + /* ptr[13] = 0; */ + /* landing zone cylinder */ + /* ptr[14] = 0; */ + /* ptr[15] = 0; */ + /* ptr[16] = 0; */ + /* RPL */ + /* ptr[17] = 0; */ + /* rotational offset */ + /* ptr[18] = 0; */ + /* medium rotation rate - 7200 RPM */ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***