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/ofw/ofw_disk.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) 2002 Benno Rice <benno@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  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  *
   25  *
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: src/sys/dev/ofw/ofw_disk.c,v 1.14.2.1 2005/01/30 00:59:56 imp Exp $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bio.h>
   34 #include <sys/module.h>
   35 #include <sys/bus.h>
   36 #include <sys/conf.h>
   37 #include <sys/kernel.h>
   38 #include <sys/limits.h>
   39 #include <geom/geom_disk.h>
   40 
   41 #include <dev/ofw/openfirm.h>
   42 
   43 #include <machine/bus.h>
   44 #include <machine/md_var.h>
   45 #include <machine/nexusvar.h>
   46 
   47 #define OFWD_BLOCKSIZE  512
   48 
   49 struct ofwd_softc
   50 {
   51         device_t        ofwd_dev;
   52         struct          disk *ofwd_disk;
   53         phandle_t       ofwd_package;
   54         ihandle_t       ofwd_instance;
   55 };
   56 
   57 /*
   58  * Disk device bus interface.
   59  */
   60 static void     ofwd_identify(driver_t *, device_t);
   61 static int      ofwd_probe(device_t);
   62 static int      ofwd_attach(device_t);
   63 
   64 static device_method_t  ofwd_methods[] = {
   65         DEVMETHOD(device_identify,      ofwd_identify),
   66         DEVMETHOD(device_probe,         ofwd_probe),
   67         DEVMETHOD(device_attach,        ofwd_attach),
   68         { 0, 0 }
   69 };
   70 
   71 static driver_t ofwd_driver = {
   72         "ofwd",
   73         ofwd_methods,
   74         sizeof(struct ofwd_softc)
   75 };
   76 
   77 static devclass_t       ofwd_devclass;
   78 
   79 DRIVER_MODULE(ofwd, nexus, ofwd_driver, ofwd_devclass, 0, 0);
   80 
   81 /*
   82  * Disk device control interface.
   83  */
   84 static disk_strategy_t  ofwd_strategy;
   85 
   86 /*
   87  * Handle an I/O request.
   88  */
   89 static void
   90 ofwd_strategy(struct bio *bp)
   91 {
   92         struct  ofwd_softc *sc;
   93         long    r;
   94 
   95         sc = (struct ofwd_softc *)bp->bio_disk->d_drv1;
   96 
   97         if (sc == NULL) {
   98                 printf("ofwd: bio for invalid disk!\n");
   99                 biofinish(bp, NULL, EINVAL);
  100                 return;
  101         }
  102 
  103         bp->bio_resid = bp->bio_bcount;
  104 
  105         r = OF_seek(sc->ofwd_instance, bp->bio_offset);
  106         if (r == -1) {
  107                 device_printf(sc->ofwd_dev, "seek failed\n");
  108                 biofinish(bp, NULL, EIO);
  109                 return;
  110         }
  111 
  112         if (bp->bio_cmd == BIO_READ) {
  113                 r = OF_read(sc->ofwd_instance, (void *)bp->bio_data,
  114                     bp->bio_bcount);
  115         } else {
  116                 r = OF_write(sc->ofwd_instance, (void *)bp->bio_data,
  117                             bp->bio_bcount);
  118         }
  119 
  120         if (r > bp->bio_bcount)
  121                 panic("ofwd: more bytes read/written than requested");
  122         if (r == -1) {
  123                 device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
  124                     r, bp->bio_bcount);
  125                 biofinish(bp, NULL, EIO);
  126                 return;
  127         }
  128 
  129         bp->bio_resid -= r;
  130 
  131         if (r < bp->bio_bcount) {
  132                 device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
  133                     r, bp->bio_bcount);
  134                 biofinish(bp, NULL, EIO);       /* XXX: probably not an error */
  135                 return;
  136         }
  137         biodone(bp);
  138         return;
  139 }
  140 
  141 /*
  142  * Attach the Open Firmware disk to nexus if present.
  143  */
  144 static void
  145 ofwd_identify(driver_t *driver, device_t parent)
  146 {
  147         device_t child;
  148         phandle_t ofd;
  149         static char type[8];
  150 
  151         ofd = OF_finddevice("ofwdisk");
  152         if (ofd == -1)
  153                 return;
  154 
  155         OF_getprop(ofd, "device_type", type, sizeof(type));
  156 
  157         child = BUS_ADD_CHILD(parent, INT_MAX, "ofwd", 0);
  158         if (child != NULL) {
  159                 nexus_set_device_type(child, type);
  160                 nexus_set_node(child, ofd);
  161         }
  162 }
  163 
  164 /*
  165  * Probe for an Open Firmware disk.
  166  */
  167 static int
  168 ofwd_probe(device_t dev)
  169 {
  170         char            *type;
  171         char            fname[32];
  172         phandle_t       node;
  173 
  174         type = nexus_get_device_type(dev);
  175         node = nexus_get_node(dev);
  176 
  177         if (type == NULL ||
  178             (strcmp(type, "disk") != 0 && strcmp(type, "block") != 0))
  179                 return (ENXIO);
  180 
  181         if (OF_getprop(node, "file", fname, sizeof(fname)) == -1)
  182                 return (ENXIO);
  183 
  184         device_set_desc(dev, "Open Firmware disk");
  185         return (0);
  186 }
  187 
  188 static int
  189 ofwd_attach(device_t dev)
  190 {
  191         struct  ofwd_softc *sc;
  192         char    path[128];
  193         char    fname[32];
  194 
  195         sc = device_get_softc(dev);
  196         sc->ofwd_dev = dev;
  197 
  198         bzero(path, 128);
  199         OF_package_to_path(nexus_get_node(dev), path, 128);
  200         OF_getprop(nexus_get_node(dev), "file", fname, sizeof(fname));
  201         device_printf(dev, "located at %s, file %s\n", path, fname);
  202         sc->ofwd_instance = OF_open(path);
  203         if (sc->ofwd_instance == -1) {
  204                 device_printf(dev, "could not create instance\n");
  205                 return (ENXIO);
  206         }
  207 
  208         sc->ofwd_disk = disk_alloc();
  209         sc->ofwd_disk->d_strategy = ofwd_strategy;
  210         sc->ofwd_disk->d_name = "ofwd";
  211         sc->ofwd_disk->d_sectorsize = OFWD_BLOCKSIZE;
  212         sc->ofwd_disk->d_mediasize = (off_t)33554432 * OFWD_BLOCKSIZE;
  213         sc->ofwd_disk->d_fwsectors = 0;
  214         sc->ofwd_disk->d_fwheads = 0;
  215         sc->ofwd_disk->d_drv1 = sc;
  216         sc->ofwd_disk->d_maxsize = PAGE_SIZE;
  217         sc->ofwd_disk->d_unit = device_get_unit(dev);
  218         sc->ofwd_disk->d_flags = DISKFLAG_NEEDSGIANT;
  219         disk_create(sc->ofwd_disk, DISK_VERSION);
  220 
  221         return (0);
  222 }

Cache object: 08ed00cb2d7cc29a29835dd30095f9ae


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