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 <bsd.subdir.mk>

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 <bsd.kmod.mk>

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 <bsd.kmod.mk>

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 <bsd.kmod.mk>

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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to