The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/pst/pst-raid.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2001,2002,2003 Søren Schmidt <sos@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer,
   10  *    without modification, immediately at the beginning of the file.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.1/sys/dev/pst/pst-raid.c 135267 2004-09-15 15:39:28Z sos $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/module.h>
   36 #include <sys/bus.h>
   37 #include <sys/bio.h>
   38 #include <sys/conf.h>
   39 #include <sys/eventhandler.h>
   40 #include <sys/malloc.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 #include <machine/stdarg.h>
   46 #include <machine/resource.h>
   47 #include <machine/bus.h>
   48 #include <sys/rman.h>
   49 #include <dev/pci/pcivar.h>
   50 #include <dev/pci/pcireg.h>
   51 #include <geom/geom_disk.h>
   52 
   53 #include "dev/pst/pst-iop.h"
   54 
   55 struct pst_softc {
   56     struct iop_softc            *iop;
   57     struct i2o_lct_entry        *lct;
   58     struct i2o_bsa_device       *info;
   59     struct disk                 *disk;
   60     struct bio_queue_head       queue;
   61 };
   62 
   63 struct pst_request {
   64     struct pst_softc            *psc;           /* pointer to softc */
   65     u_int32_t                   mfa;            /* frame addreess */
   66     struct callout_handle       timeout_handle; /* handle for untimeout */
   67     struct bio                  *bp;            /* associated bio ptr */
   68 };
   69 
   70 /* prototypes */
   71 static disk_strategy_t pststrategy;
   72 static int pst_probe(device_t);
   73 static int pst_attach(device_t);
   74 static int pst_shutdown(device_t);
   75 static void pst_start(struct pst_softc *);
   76 static void pst_done(struct iop_softc *, u_int32_t, struct i2o_single_reply *);
   77 static int pst_rw(struct pst_request *);
   78 static void pst_timeout(struct pst_request *);
   79 static void bpack(int8_t *, int8_t *, int);
   80 
   81 /* local vars */
   82 static MALLOC_DEFINE(M_PSTRAID, "pst", "Promise SuperTrak RAID driver");
   83 
   84 int
   85 pst_add_raid(struct iop_softc *sc, struct i2o_lct_entry *lct)
   86 {
   87     struct pst_softc *psc;
   88     device_t child = device_add_child(sc->dev, "pst", -1);
   89 
   90     if (!child)
   91         return ENOMEM;
   92     if (!(psc = malloc(sizeof(struct pst_softc), 
   93                        M_PSTRAID, M_NOWAIT | M_ZERO))) {
   94         device_delete_child(sc->dev, child);
   95         return ENOMEM;
   96     }
   97     psc->iop = sc;
   98     psc->lct = lct;
   99     device_set_softc(child, psc);
  100     return bus_generic_attach(sc->dev);
  101 }
  102 
  103 static int
  104 pst_probe(device_t dev)
  105 {
  106     device_set_desc(dev, "Promise SuperTrak RAID");
  107     return 0;
  108 }
  109 
  110 static int
  111 pst_attach(device_t dev)
  112 {
  113     struct pst_softc *psc = device_get_softc(dev);
  114     struct i2o_get_param_reply *reply;
  115     struct i2o_device_identity *ident;
  116     int lun = device_get_unit(dev);
  117     int8_t name [32];
  118 
  119     if (!(reply = iop_get_util_params(psc->iop, psc->lct->local_tid,
  120                                       I2O_PARAMS_OPERATION_FIELD_GET,
  121                                       I2O_BSA_DEVICE_INFO_GROUP_NO)))
  122         return ENODEV;
  123 
  124     if (!(psc->info = (struct i2o_bsa_device *)
  125             malloc(sizeof(struct i2o_bsa_device), M_PSTRAID, M_NOWAIT))) {
  126         contigfree(reply, PAGE_SIZE, M_PSTIOP);
  127         return ENOMEM;
  128     }
  129     bcopy(reply->result, psc->info, sizeof(struct i2o_bsa_device));
  130     contigfree(reply, PAGE_SIZE, M_PSTIOP);
  131 
  132     if (!(reply = iop_get_util_params(psc->iop, psc->lct->local_tid,
  133                                       I2O_PARAMS_OPERATION_FIELD_GET,
  134                                       I2O_UTIL_DEVICE_IDENTITY_GROUP_NO)))
  135         return ENODEV;
  136     ident = (struct i2o_device_identity *)reply->result;
  137 #ifdef PSTDEBUG    
  138     printf("pst: vendor=<%.16s> product=<%.16s>\n",
  139            ident->vendor, ident->product);
  140     printf("pst: description=<%.16s> revision=<%.8s>\n",
  141            ident->description, ident->revision);
  142     printf("pst: capacity=%lld blocksize=%d\n",
  143            psc->info->capacity, psc->info->block_size);
  144 #endif
  145     bpack(ident->vendor, ident->vendor, 16);
  146     bpack(ident->product, ident->product, 16);
  147     sprintf(name, "%s %s", ident->vendor, ident->product);
  148     contigfree(reply, PAGE_SIZE, M_PSTIOP);
  149 
  150     bioq_init(&psc->queue);
  151 
  152     psc->disk = disk_alloc();
  153     psc->disk->d_name = "pst";
  154     psc->disk->d_strategy = pststrategy;
  155     psc->disk->d_maxsize = 64 * 1024; /*I2O_SGL_MAX_SEGS * PAGE_SIZE;*/
  156     psc->disk->d_drv1 = psc;
  157     psc->disk->d_unit = lun;
  158 
  159     psc->disk->d_sectorsize = psc->info->block_size;
  160     psc->disk->d_mediasize = psc->info->capacity;
  161     psc->disk->d_fwsectors = 63;
  162     psc->disk->d_fwheads = 255;
  163 
  164     disk_create(psc->disk, DISK_VERSION);
  165 
  166     printf("pst%d: %lluMB <%.40s> [%lld/%d/%d] on %.16s\n", lun,
  167            (unsigned long long)psc->info->capacity / (1024 * 1024),
  168            name, psc->info->capacity/(512*255*63), 255, 63,
  169            device_get_nameunit(psc->iop->dev));
  170 
  171     EVENTHANDLER_REGISTER(shutdown_post_sync, pst_shutdown,
  172                           dev, SHUTDOWN_PRI_FIRST);
  173     return 0;
  174 }
  175 
  176 static int
  177 pst_shutdown(device_t dev)
  178 {
  179     struct pst_softc *psc = device_get_softc(dev);
  180     struct i2o_bsa_cache_flush_message *msg;
  181     int mfa;
  182 
  183     mfa = iop_get_mfa(psc->iop);
  184     msg = (struct i2o_bsa_cache_flush_message *)(psc->iop->ibase + mfa);
  185     bzero(msg, sizeof(struct i2o_bsa_cache_flush_message));
  186     msg->version_offset = 0x01;
  187     msg->message_flags = 0x0;
  188     msg->message_size = sizeof(struct i2o_bsa_cache_flush_message) >> 2;
  189     msg->target_address = psc->lct->local_tid;
  190     msg->initiator_address = I2O_TID_HOST;
  191     msg->function = I2O_BSA_CACHE_FLUSH;
  192     msg->control_flags = 0x0; /* 0x80 = post progress reports */
  193     if (iop_queue_wait_msg(psc->iop, mfa, (struct i2o_basic_message *)msg))
  194         printf("pst: shutdown failed!\n");
  195     return 0;
  196 }
  197 
  198 static void
  199 pststrategy(struct bio *bp)
  200 {
  201     struct pst_softc *psc = bp->bio_disk->d_drv1;
  202     
  203     mtx_lock(&psc->iop->mtx);
  204     bioq_disksort(&psc->queue, bp);
  205     pst_start(psc);
  206     mtx_unlock(&psc->iop->mtx);
  207 }
  208 
  209 static void
  210 pst_start(struct pst_softc *psc)
  211 {
  212     struct pst_request *request;
  213     struct bio *bp;
  214     u_int32_t mfa;
  215 
  216     if (psc->iop->outstanding < (I2O_IOP_OUTBOUND_FRAME_COUNT - 1) &&
  217         (bp = bioq_first(&psc->queue))) {
  218         if ((mfa = iop_get_mfa(psc->iop)) != 0xffffffff) {
  219             bioq_remove(&psc->queue, bp);
  220             if (!(request = malloc(sizeof(struct pst_request),
  221                                    M_PSTRAID, M_NOWAIT | M_ZERO))) {
  222                 printf("pst: out of memory in start\n");
  223                 biofinish(request->bp, NULL, ENOMEM);
  224                 iop_free_mfa(psc->iop, mfa);
  225                 return;
  226             }
  227             psc->iop->outstanding++;
  228             request->psc = psc;
  229             request->mfa = mfa;
  230             request->bp = bp;
  231             if (pst_rw(request)) {
  232                 biofinish(request->bp, NULL, EIO);
  233                 iop_free_mfa(request->psc->iop, request->mfa);
  234                 psc->iop->outstanding--;
  235                 free(request, M_PSTRAID);
  236             }
  237         }
  238     }
  239 }
  240 
  241 static void
  242 pst_done(struct iop_softc *sc, u_int32_t mfa, struct i2o_single_reply *reply)
  243 {
  244     struct pst_request *request =
  245         (struct pst_request *)reply->transaction_context;
  246     struct pst_softc *psc = request->psc;
  247 
  248     untimeout((timeout_t *)pst_timeout, request, request->timeout_handle);
  249     request->bp->bio_resid = request->bp->bio_bcount - reply->donecount;
  250     biofinish(request->bp, NULL, reply->status ? EIO : 0);
  251     free(request, M_PSTRAID);
  252     psc->iop->reg->oqueue = mfa;
  253     psc->iop->outstanding--;
  254     pst_start(psc);
  255 }
  256 
  257 int
  258 pst_rw(struct pst_request *request)
  259 {
  260     struct i2o_bsa_rw_block_message *msg;
  261     int sgl_flag;
  262 
  263     msg = (struct i2o_bsa_rw_block_message *)
  264           (request->psc->iop->ibase + request->mfa);
  265     bzero(msg, sizeof(struct i2o_bsa_rw_block_message));
  266     msg->version_offset = 0x81;
  267     msg->message_flags = 0x0;
  268     msg->message_size = sizeof(struct i2o_bsa_rw_block_message) >> 2;
  269     msg->target_address = request->psc->lct->local_tid;
  270     msg->initiator_address = I2O_TID_HOST;
  271     switch (request->bp->bio_cmd) {
  272     case BIO_READ:
  273         msg->function = I2O_BSA_BLOCK_READ;
  274         msg->control_flags = 0x0; /* 0x0c = read cache + readahead */
  275         msg->fetch_ahead = 0x0; /* 8 Kb */
  276         sgl_flag = 0;
  277         break;
  278     case BIO_WRITE:
  279         msg->function = I2O_BSA_BLOCK_WRITE;
  280         msg->control_flags = 0x0; /* 0x10 = write behind cache */
  281         msg->fetch_ahead = 0x0;
  282         sgl_flag = I2O_SGL_DIR;
  283         break;
  284     default:
  285         printf("pst: unknown command type 0x%02x\n", request->bp->bio_cmd);
  286         return -1;
  287     }
  288     msg->initiator_context = (u_int32_t)pst_done;
  289     msg->transaction_context = (u_int32_t)request;
  290     msg->time_multiplier = 1;
  291     msg->bytecount = request->bp->bio_bcount;
  292     msg->lba = ((u_int64_t)request->bp->bio_pblkno) * (DEV_BSIZE * 1LL);
  293 
  294     if (!iop_create_sgl((struct i2o_basic_message *)msg, request->bp->bio_data,
  295                         request->bp->bio_bcount, sgl_flag))
  296         return -1;
  297 
  298     request->psc->iop->reg->iqueue = request->mfa;
  299 
  300     if (dumping)
  301         request->timeout_handle.callout = NULL;
  302     else
  303         request->timeout_handle = 
  304             timeout((timeout_t*)pst_timeout, request, 10 * hz);
  305     return 0;
  306 }
  307 
  308 static void
  309 pst_timeout(struct pst_request *request)
  310 {
  311     printf("pst: timeout mfa=0x%08x cmd=0x%02x\n",
  312            request->mfa, request->bp->bio_cmd);
  313     mtx_lock(&request->psc->iop->mtx);
  314     iop_free_mfa(request->psc->iop, request->mfa);
  315     if ((request->mfa = iop_get_mfa(request->psc->iop)) == 0xffffffff) {
  316         printf("pst: timeout no mfa possible\n");
  317         biofinish(request->bp, NULL, EIO);
  318         request->psc->iop->outstanding--;
  319         mtx_unlock(&request->psc->iop->mtx);
  320         return;
  321     }
  322     if (pst_rw(request)) {
  323         iop_free_mfa(request->psc->iop, request->mfa);
  324         biofinish(request->bp, NULL, EIO);
  325         request->psc->iop->outstanding--;
  326     }
  327     mtx_unlock(&request->psc->iop->mtx);
  328 }
  329 
  330 static void
  331 bpack(int8_t *src, int8_t *dst, int len)
  332 {
  333     int i, j, blank;
  334     int8_t *ptr, *buf = dst;
  335 
  336     for (i = j = blank = 0 ; i < len; i++) {
  337         if (blank && src[i] == ' ')
  338             continue;
  339         if (blank && src[i] != ' ') {
  340             dst[j++] = src[i];
  341             blank = 0;
  342             continue;
  343         }
  344         if (src[i] == ' ') {
  345             blank = 1;
  346             if (i == 0)
  347                 continue;
  348         }
  349         dst[j++] = src[i];
  350     }
  351     if (j < len) 
  352         dst[j] = 0x00;
  353     for (ptr = buf; ptr < buf+len; ++ptr)
  354         if (!*ptr)
  355             *ptr = ' ';
  356     for (ptr = buf + len - 1; ptr >= buf && *ptr == ' '; --ptr)
  357         *ptr = 0;
  358 }
  359 
  360 static device_method_t pst_methods[] = {
  361     DEVMETHOD(device_probe,     pst_probe),
  362     DEVMETHOD(device_attach,    pst_attach),
  363     { 0, 0 }
  364 };
  365         
  366 static driver_t pst_driver = {
  367     "pst",
  368     pst_methods,
  369     sizeof(struct pst_softc),
  370 };
  371 
  372 static devclass_t pst_devclass;
  373 
  374 DRIVER_MODULE(pst, pstpci, pst_driver, pst_devclass, 0, 0);

Cache object: 25ed50df0a5391079e516b3e1f51a456


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.