1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  * Ramdisk device driver.
  29  *
  30  * There are two types of ramdisk: 'real' OBP-created ramdisks, and 'pseudo'
  31  * ramdisks created at runtime with no corresponding OBP device node.  The
  32  * ramdisk(7D) driver is capable of dealing with both, and with the creation
  33  * and deletion of 'pseudo' ramdisks.
  34  *
  35  * Every ramdisk has a single 'state' structure which maintains data for
  36  * that ramdisk, and is assigned a single minor number.  The bottom 10-bits
  37  * of the minor number index the state structures; the top 8-bits give a
  38  * 'real OBP disk' number, i.e. they are zero for 'pseudo' ramdisks.  Thus
  39  * it is possible to distinguish 'real' from 'pseudo' ramdisks using the
  40  * top 8-bits of the minor number.
  41  *
  42  * Each OBP-created ramdisk has its own node in the device tree with an
  43  * "existing" property which describes the one-or-more physical address ranges
  44  * assigned to the ramdisk.  All 'pseudo' ramdisks share a common devinfo
  45  * structure.
  46  *
  47  * A single character device node is used by ramdiskadm(1M) to communicate
  48  * with the ramdisk driver, with minor number 0:
  49  *
  50  *      /dev/ramdiskctl -> /devices/pseudo/ramdisk@0:ctl
  51  *
  52  * For consistent access, block and raw device nodes are created for *every*
  53  * ramdisk.  For 'pseudo' ramdisks:
  54  *
  55  *      /dev/ramdisk/<diskname>  -> /devices/pseudo/ramdisk@0:<diskname>
  56  *      /dev/rramdisk/<diskname> -> /devices/pseudo/ramdisk@0:<diskname>,raw
  57  *
  58  * For OBP-created ramdisks:
  59  *
  60  *      /dev/ramdisk/<diskname>  -> /devices/ramdisk-<diskname>:a
  61  *      /dev/ramdisk/<diskname>  -> /devices/ramdisk-<diskname>:a,raw
  62  *
  63  * This allows the transition from the standalone to the kernel to proceed
  64  * when booting from a ramdisk, and for the installation to correctly identify
  65  * the root device.
  66  */
  67 
  68 #include <sys/types.h>
  69 #include <sys/param.h>
  70 #include <sys/sysmacros.h>
  71 #include <sys/errno.h>
  72 #include <sys/uio.h>
  73 #include <sys/buf.h>
  74 #include <sys/modctl.h>
  75 #include <sys/open.h>
  76 #include <sys/kmem.h>
  77 #include <sys/poll.h>
  78 #include <sys/conf.h>
  79 #include <sys/cmn_err.h>
  80 #include <sys/stat.h>
  81 #include <sys/file.h>
  82 #include <sys/ddi.h>
  83 #include <sys/sunddi.h>
  84 #include <sys/ramdisk.h>
  85 #include <vm/seg_kmem.h>
  86 
  87 /*
  88  * Flag to disable the use of real ramdisks (in the OBP - on Sparc) when
  89  * the associated memory is no longer available - set in the bootops section.
  90  */
  91 #ifdef __sparc
  92 extern int bootops_obp_ramdisk_disabled;
  93 #endif /* __sparc */
  94 
  95 /*
  96  * An opaque handle where information about our set of ramdisk devices lives.
  97  */
  98 static void     *rd_statep;
  99 
 100 /*
 101  * Pointer to devinfo for the 'pseudo' ramdisks.  Real OBP-created ramdisks
 102  * get their own individual devinfo.
 103  */
 104 static dev_info_t *rd_dip = NULL;
 105 
 106 /*
 107  * Global state lock.
 108  */
 109 static kmutex_t rd_lock;
 110 
 111 /*
 112  * Maximum number of ramdisks supported by this driver.
 113  */
 114 static uint32_t rd_max_disks = RD_DFLT_DISKS;
 115 
 116 /*
 117  * Percentage of physical memory which can be assigned to pseudo ramdisks,
 118  * what that equates to in pages, and how many pages are currently assigned.
 119  */
 120 static uint_t   rd_percent_physmem = RD_DEFAULT_PERCENT_PHYSMEM;
 121 static pgcnt_t  rd_max_physmem;
 122 static pgcnt_t  rd_tot_physmem;
 123 
 124 static uint_t   rd_maxphys = RD_DEFAULT_MAXPHYS;
 125 
 126 /*
 127  * Is the driver busy, i.e. are there any pseudo ramdisk devices in existence?
 128  */
 129 static int
 130 rd_is_busy(void)
 131 {
 132         minor_t minor;
 133         rd_devstate_t   *rsp;
 134 
 135         ASSERT(mutex_owned(&rd_lock));
 136         for (minor = 1; minor <= rd_max_disks; ++minor) {
 137                 if ((rsp = ddi_get_soft_state(rd_statep, minor)) != NULL &&
 138                     rsp->rd_dip == rd_dip) {
 139                         return (EBUSY);
 140                 }
 141         }
 142         return (0);
 143 }
 144 
 145 /*
 146  * Find the first free minor number; returns zero if there isn't one.
 147  */
 148 static minor_t
 149 rd_find_free_minor(void)
 150 {
 151         minor_t minor;
 152 
 153         ASSERT(mutex_owned(&rd_lock));
 154         for (minor = 1; minor <= rd_max_disks; ++minor) {
 155                 if (ddi_get_soft_state(rd_statep, minor) == NULL) {
 156                         return (minor);
 157                 }
 158         }
 159         return (0);
 160 }
 161 
 162 /*
 163  * Locate the rd_devstate for the named ramdisk; returns NULL if not found.
 164  * Each ramdisk is identified uniquely by name, i.e. an OBP-created ramdisk
 165  * cannot have the same name as a pseudo ramdisk.
 166  */
 167 static rd_devstate_t *
 168 rd_find_named_disk(char *name)
 169 {
 170         minor_t         minor;
 171         rd_devstate_t   *rsp;
 172 
 173         ASSERT(mutex_owned(&rd_lock));
 174         for (minor = 1; minor <= rd_max_disks; ++minor) {
 175                 if ((rsp = ddi_get_soft_state(rd_statep, minor)) != NULL &&
 176                     strcmp(rsp->rd_name, name) == 0) {
 177                         return (rsp);
 178                 }
 179         }
 180         return (NULL);
 181 }
 182 
 183 /*
 184  * Locate the rd_devstate for the real OBP-created ramdisk whose devinfo
 185  * is referenced by 'dip'; returns NULL if not found (shouldn't happen).
 186  */
 187 static rd_devstate_t *
 188 rd_find_dip_state(dev_info_t *dip)
 189 {
 190         minor_t         minor;
 191         rd_devstate_t   *rsp;
 192 
 193         ASSERT(mutex_owned(&rd_lock));
 194         for (minor = 1; minor <= rd_max_disks; ++minor) {
 195                 if ((rsp = ddi_get_soft_state(rd_statep, minor)) != NULL &&
 196                     rsp->rd_dip == dip) {
 197                         return (rsp);
 198                 }
 199         }
 200         return (NULL);
 201 }
 202 
 203 /*
 204  * Is the ramdisk open?
 205  */
 206 static int
 207 rd_is_open(rd_devstate_t *rsp)
 208 {
 209         ASSERT(mutex_owned(&rd_lock));
 210         return (rsp->rd_chr_open || rsp->rd_blk_open || rsp->rd_lyr_open_cnt);
 211 }
 212 
 213 /*
 214  * Mark the ramdisk open.
 215  */
 216 static int
 217 rd_opened(rd_devstate_t *rsp, int otyp)
 218 {
 219         ASSERT(mutex_owned(&rd_lock));
 220         switch (otyp) {
 221         case OTYP_CHR:
 222                 rsp->rd_chr_open = 1;
 223                 break;
 224         case OTYP_BLK:
 225                 rsp->rd_blk_open = 1;
 226                 break;
 227         case OTYP_LYR:
 228                 rsp->rd_lyr_open_cnt++;
 229                 break;
 230         default:
 231                 return (-1);
 232         }
 233         return (0);
 234 }
 235 
 236 /*
 237  * Mark the ramdisk closed.
 238  */
 239 static void
 240 rd_closed(rd_devstate_t *rsp, int otyp)
 241 {
 242         ASSERT(mutex_owned(&rd_lock));
 243         switch (otyp) {
 244         case OTYP_CHR:
 245                 rsp->rd_chr_open = 0;
 246                 break;
 247         case OTYP_BLK:
 248                 rsp->rd_blk_open = 0;
 249                 break;
 250         case OTYP_LYR:
 251                 rsp->rd_lyr_open_cnt--;
 252                 break;
 253         default:
 254                 break;
 255         }
 256 }
 257 
 258 static void
 259 rd_init_tuneables(void)
 260 {
 261         char    *prop, *p;
 262 
 263         /*
 264          * Ensure sanity of 'rd_max_disks', which may be tuned in ramdisk.conf.
 265          */
 266         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, rd_dip, 0,
 267             "max_disks", &prop) == DDI_PROP_SUCCESS) {
 268                 p = prop;
 269                 rd_max_disks = (uint32_t)stoi(&p);
 270                 ddi_prop_free(prop);
 271         }
 272         if (rd_max_disks >= RD_MAX_DISKS) {
 273                 cmn_err(CE_WARN, "ramdisk: rd_max_disks (%u) too big;"
 274                     " using default (%u).", rd_max_disks, RD_MAX_DISKS - 1);
 275 
 276                 rd_max_disks = RD_MAX_DISKS - 1;
 277         }
 278 
 279         /*
 280          * Ensure sanity of 'rd_percent_physmem', which may be tuned
 281          * in ramdisk.conf.
 282          */
 283         if (ddi_prop_lookup_string(DDI_DEV_T_ANY, rd_dip, 0,
 284             "percent_physmem", &prop) == DDI_PROP_SUCCESS) {
 285                 p = prop;
 286                 rd_percent_physmem = (uint_t)stoi(&p);
 287                 ddi_prop_free(prop);
 288         }
 289         if (rd_percent_physmem >= 100) {
 290                 cmn_err(CE_WARN, "ramdisk: rd_percent_physmem (%u) >= 100;"
 291                     " using default (%u%%).", rd_percent_physmem,
 292                     RD_DEFAULT_PERCENT_PHYSMEM);
 293 
 294                 rd_percent_physmem = RD_DEFAULT_PERCENT_PHYSMEM;
 295         }
 296 
 297         /*
 298          * Since availrmem_initial is a long, this won't overflow.
 299          */
 300         rd_max_physmem = (availrmem_initial * rd_percent_physmem) / 100;
 301 }
 302 
 303 /*
 304  * Allocate enough physical pages to hold "npages" pages.  Returns an
 305  * array of page_t * pointers that can later be mapped in or out via
 306  * rd_{un}map_window() but is otherwise opaque, or NULL on failure.
 307  */
 308 page_t **
 309 rd_phys_alloc(pgcnt_t npages)
 310 {
 311         page_t          *pp, **ppa;
 312         spgcnt_t        i;
 313         size_t          ppalen;
 314         struct seg      kseg;
 315         caddr_t         addr;           /* For coloring */
 316 
 317         if (rd_tot_physmem + npages > rd_max_physmem)
 318                 return (NULL);
 319 
 320         if (!page_resv(npages, KM_NOSLEEP))
 321                 return (NULL);
 322 
 323         if (!page_create_wait(npages, 0)) {
 324                 page_unresv(npages);
 325                 return (NULL);
 326         }
 327 
 328         ppalen = npages * sizeof (struct page_t *);
 329         ppa = kmem_zalloc(ppalen, KM_NOSLEEP);
 330         if (ppa == NULL) {
 331                 page_create_putback(npages);
 332                 page_unresv(npages);
 333                 return (NULL);
 334         }
 335 
 336         kseg.s_as = &kas;
 337         for (i = 0, addr = NULL; i < npages; ++i, addr += PAGESIZE) {
 338                 pp = page_get_freelist(&kvp, 0, &kseg, addr, PAGESIZE, 0, NULL);
 339                 if (pp == NULL) {
 340                         pp = page_get_cachelist(&kvp, 0, &kseg, addr, 0, NULL);
 341                         if (pp == NULL)
 342                                 goto out;
 343                         if (!PP_ISAGED(pp))
 344                                 page_hashout(pp, NULL);
 345                 }
 346 
 347                 PP_CLRFREE(pp);
 348                 PP_CLRAGED(pp);
 349                 ppa[i] = pp;
 350         }
 351 
 352         for (i = 0; i < npages; i++)
 353                 page_downgrade(ppa[i]);
 354         rd_tot_physmem += npages;
 355 
 356         return (ppa);
 357 
 358 out:
 359         ASSERT(i < npages);
 360         page_create_putback(npages - i);
 361         while (--i >= 0)
 362                 page_free(ppa[i], 0);
 363         kmem_free(ppa, ppalen);
 364         page_unresv(npages);
 365 
 366         return (NULL);
 367 }
 368 
 369 /*
 370  * Free physical pages previously allocated via rd_phys_alloc(); note that
 371  * this function may block as it has to wait until it can exclusively lock
 372  * all the pages first.
 373  */
 374 static void
 375 rd_phys_free(page_t **ppa, pgcnt_t npages)
 376 {
 377         pgcnt_t i;
 378         size_t  ppalen = npages * sizeof (struct page_t *);
 379 
 380         for (i = 0; i < npages; ++i) {
 381                 if (! page_tryupgrade(ppa[i])) {
 382                         page_unlock(ppa[i]);
 383                         while (! page_lock(ppa[i], SE_EXCL, NULL, P_RECLAIM))
 384                                 ;
 385                 }
 386                 page_free(ppa[i], 0);
 387         }
 388 
 389         kmem_free(ppa, ppalen);
 390 
 391         page_unresv(npages);
 392         rd_tot_physmem -= npages;
 393 }
 394 
 395 /*
 396  * Remove a window mapping (if present).
 397  */
 398 static void
 399 rd_unmap_window(rd_devstate_t *rsp)
 400 {
 401         ASSERT(rsp->rd_window_obp == 0);
 402         if (rsp->rd_window_base != RD_WINDOW_NOT_MAPPED) {
 403                 hat_unload(kas.a_hat, rsp->rd_window_virt, rsp->rd_window_size,
 404                     HAT_UNLOAD_UNLOCK);
 405         }
 406 }
 407 
 408 /*
 409  * Map a portion of the ramdisk into the virtual window.
 410  */
 411 static void
 412 rd_map_window(rd_devstate_t *rsp, off_t offset)
 413 {
 414         pgcnt_t offpgs = btop(offset);
 415 
 416         if (rsp->rd_window_base != RD_WINDOW_NOT_MAPPED) {
 417                 /*
 418                  * Already mapped; is offset within our window?
 419                  */
 420                 if (offset >= rsp->rd_window_base &&
 421                     offset < rsp->rd_window_base + rsp->rd_window_size) {
 422                         return;
 423                 }
 424 
 425                 /*
 426                  * No, we need to re-map; toss the old mapping.
 427                  */
 428                 rd_unmap_window(rsp);
 429         }
 430         rsp->rd_window_base = ptob(offpgs);
 431 
 432         /*
 433          * Different algorithms depending on whether this is a real
 434          * OBP-created ramdisk, or a pseudo ramdisk.
 435          */
 436         if (rsp->rd_dip == rd_dip) {
 437                 pgcnt_t pi, lastpi;
 438                 caddr_t vaddr;
 439 
 440                 /*
 441                  * Find the range of pages which should be mapped.
 442                  */
 443                 pi = offpgs;
 444                 lastpi = pi + btopr(rsp->rd_window_size);
 445                 if (lastpi > rsp->rd_npages) {
 446                         lastpi = rsp->rd_npages;
 447                 }
 448 
 449                 /*
 450                  * Load the mapping.
 451                  */
 452                 vaddr = rsp->rd_window_virt;
 453                 for (; pi < lastpi; ++pi) {
 454                         hat_memload(kas.a_hat, vaddr, rsp->rd_ppa[pi],
 455                             (PROT_READ | PROT_WRITE) | HAT_NOSYNC,
 456                             HAT_LOAD_LOCK);
 457                         vaddr += ptob(1);
 458                 }
 459         } else {
 460                 uint_t  i;
 461                 pfn_t   pfn;
 462 
 463                 /*
 464                  * Real OBP-created ramdisk: locate the physical range which
 465                  * contains this offset.
 466                  */
 467                 for (i = 0; i < rsp->rd_nexisting; ++i) {
 468                         if (offset < rsp->rd_existing[i].size) {
 469                                 break;
 470                         }
 471                         offset -= rsp->rd_existing[i].size;
 472                 }
 473                 ASSERT(i < rsp->rd_nexisting);
 474 
 475                 /*
 476                  * Load the mapping.
 477                  */
 478                 pfn = btop(rsp->rd_existing[i].phys + offset);
 479                 hat_devload(kas.a_hat, rsp->rd_window_virt, rsp->rd_window_size,
 480                     pfn, (PROT_READ | PROT_WRITE),
 481                     HAT_LOAD_NOCONSIST | HAT_LOAD_LOCK);
 482         }
 483 }
 484 
 485 /*
 486  * Fakes up a disk geometry, and one big partition, based on the size
 487  * of the file. This is needed because we allow newfs'ing the device,
 488  * and newfs will do several disk ioctls to figure out the geometry and
 489  * partition information. It uses that information to determine the parameters
 490  * to pass to mkfs. Geometry is pretty much irrelevant these days, but we
 491  * have to support it.
 492  *
 493  * Stolen from lofi.c - should maybe split out common code sometime.
 494  */
 495 static void
 496 rd_fake_disk_geometry(rd_devstate_t *rsp)
 497 {
 498         /* dk_geom - see dkio(7I) */
 499         /*
 500          * dkg_ncyl _could_ be set to one here (one big cylinder with gobs
 501          * of sectors), but that breaks programs like fdisk which want to
 502          * partition a disk by cylinder. With one cylinder, you can't create
 503          * an fdisk partition and put pcfs on it for testing (hard to pick
 504          * a number between one and one).
 505          *
 506          * The cheezy floppy test is an attempt to not have too few cylinders
 507          * for a small file, or so many on a big file that you waste space
 508          * for backup superblocks or cylinder group structures.
 509          */
 510         if (rsp->rd_size < (2 * 1024 * 1024)) /* floppy? */
 511                 rsp->rd_dkg.dkg_ncyl = rsp->rd_size / (100 * 1024);
 512         else
 513                 rsp->rd_dkg.dkg_ncyl = rsp->rd_size / (300 * 1024);
 514         /* in case file file is < 100k */
 515         if (rsp->rd_dkg.dkg_ncyl == 0)
 516                 rsp->rd_dkg.dkg_ncyl = 1;
 517         rsp->rd_dkg.dkg_acyl = 0;
 518         rsp->rd_dkg.dkg_bcyl = 0;
 519         rsp->rd_dkg.dkg_nhead = 1;
 520         rsp->rd_dkg.dkg_obs1 = 0;
 521         rsp->rd_dkg.dkg_intrlv = 0;
 522         rsp->rd_dkg.dkg_obs2 = 0;
 523         rsp->rd_dkg.dkg_obs3 = 0;
 524         rsp->rd_dkg.dkg_apc = 0;
 525         rsp->rd_dkg.dkg_rpm = 7200;
 526         rsp->rd_dkg.dkg_pcyl = rsp->rd_dkg.dkg_ncyl + rsp->rd_dkg.dkg_acyl;
 527         rsp->rd_dkg.dkg_nsect = rsp->rd_size /
 528             (DEV_BSIZE * rsp->rd_dkg.dkg_ncyl);
 529         rsp->rd_dkg.dkg_write_reinstruct = 0;
 530         rsp->rd_dkg.dkg_read_reinstruct = 0;
 531 
 532         /* vtoc - see dkio(7I) */
 533         bzero(&rsp->rd_vtoc, sizeof (struct vtoc));
 534         rsp->rd_vtoc.v_sanity = VTOC_SANE;
 535         rsp->rd_vtoc.v_version = V_VERSION;
 536         bcopy(RD_DRIVER_NAME, rsp->rd_vtoc.v_volume, 7);
 537         rsp->rd_vtoc.v_sectorsz = DEV_BSIZE;
 538         rsp->rd_vtoc.v_nparts = 1;
 539         rsp->rd_vtoc.v_part[0].p_tag = V_UNASSIGNED;
 540         rsp->rd_vtoc.v_part[0].p_flag = V_UNMNT;
 541         rsp->rd_vtoc.v_part[0].p_start = (daddr_t)0;
 542         /*
 543          * The partition size cannot just be the number of sectors, because
 544          * that might not end on a cylinder boundary. And if that's the case,
 545          * newfs/mkfs will print a scary warning. So just figure the size
 546          * based on the number of cylinders and sectors/cylinder.
 547          */
 548         rsp->rd_vtoc.v_part[0].p_size = rsp->rd_dkg.dkg_pcyl *
 549             rsp->rd_dkg.dkg_nsect * rsp->rd_dkg.dkg_nhead;
 550 
 551         /* dk_cinfo - see dkio(7I) */
 552         bzero(&rsp->rd_ci, sizeof (struct dk_cinfo));
 553         (void) strcpy(rsp->rd_ci.dki_cname, RD_DRIVER_NAME);
 554         rsp->rd_ci.dki_ctype = DKC_MD;
 555         rsp->rd_ci.dki_flags = 0;
 556         rsp->rd_ci.dki_cnum = 0;
 557         rsp->rd_ci.dki_addr = 0;
 558         rsp->rd_ci.dki_space = 0;
 559         rsp->rd_ci.dki_prio = 0;
 560         rsp->rd_ci.dki_vec = 0;
 561         (void) strcpy(rsp->rd_ci.dki_dname, RD_DRIVER_NAME);
 562         rsp->rd_ci.dki_unit = 0;
 563         rsp->rd_ci.dki_slave = 0;
 564         rsp->rd_ci.dki_partition = 0;
 565         /*
 566          * newfs uses this to set maxcontig. Must not be < 16, or it
 567          * will be 0 when newfs multiplies it by DEV_BSIZE and divides
 568          * it by the block size. Then tunefs doesn't work because
 569          * maxcontig is 0.
 570          */
 571         rsp->rd_ci.dki_maxtransfer = 16;
 572 }
 573 
 574 /*
 575  * Deallocate resources (virtual and physical, device nodes, structures)
 576  * from a ramdisk.
 577  */
 578 static void
 579 rd_dealloc_resources(rd_devstate_t *rsp)
 580 {
 581         dev_info_t      *dip = rsp->rd_dip;
 582         char            namebuf[RD_NAME_LEN + 5];
 583         dev_t           fulldev;
 584 
 585         if (rsp->rd_window_obp == 0 && rsp->rd_window_virt != NULL) {
 586                 if (rsp->rd_window_base != RD_WINDOW_NOT_MAPPED) {
 587                         rd_unmap_window(rsp);
 588                 }
 589                 vmem_free(heap_arena, rsp->rd_window_virt, rsp->rd_window_size);
 590         }
 591         mutex_destroy(&rsp->rd_device_lock);
 592 
 593         if (rsp->rd_existing) {
 594                 ddi_prop_free(rsp->rd_existing);
 595         }
 596         if (rsp->rd_ppa != NULL) {
 597                 rd_phys_free(rsp->rd_ppa, rsp->rd_npages);
 598         }
 599 
 600         /*
 601          * Remove the block and raw device nodes.
 602          */
 603         if (dip == rd_dip) {
 604                 (void) snprintf(namebuf, sizeof (namebuf), "%s",
 605                     rsp->rd_name);
 606                 ddi_remove_minor_node(dip, namebuf);
 607                 (void) snprintf(namebuf, sizeof (namebuf), "%s,raw",
 608                     rsp->rd_name);
 609                 ddi_remove_minor_node(dip, namebuf);
 610         } else {
 611                 ddi_remove_minor_node(dip, "a");
 612                 ddi_remove_minor_node(dip, "a,raw");
 613         }
 614 
 615         /*
 616          * Remove the "Size" and "Nblocks" properties.
 617          */
 618         fulldev = makedevice(ddi_driver_major(dip), rsp->rd_minor);
 619         (void) ddi_prop_remove(fulldev, dip, SIZE_PROP_NAME);
 620         (void) ddi_prop_remove(fulldev, dip, NBLOCKS_PROP_NAME);
 621 
 622         if (rsp->rd_kstat) {
 623                 kstat_delete(rsp->rd_kstat);
 624                 mutex_destroy(&rsp->rd_kstat_lock);
 625         }
 626 
 627         ddi_soft_state_free(rd_statep, rsp->rd_minor);
 628 }
 629 
 630 /*
 631  * Allocate resources (virtual and physical, device nodes, structures)
 632  * to a ramdisk.
 633  */
 634 static rd_devstate_t *
 635 rd_alloc_resources(char *name, uint_t addr, size_t size, dev_info_t *dip)
 636 {
 637         minor_t         minor;
 638         rd_devstate_t   *rsp;
 639         char            namebuf[RD_NAME_LEN + 5];
 640         dev_t           fulldev;
 641         int64_t         Nblocks_prop_val;
 642         int64_t         Size_prop_val;
 643 
 644         minor = rd_find_free_minor();
 645         if (ddi_soft_state_zalloc(rd_statep, minor) == DDI_FAILURE) {
 646                 return (NULL);
 647         }
 648         rsp = ddi_get_soft_state(rd_statep, minor);
 649 
 650         (void) strcpy(rsp->rd_name, name);
 651         rsp->rd_dip = dip;
 652         rsp->rd_minor = minor;
 653         rsp->rd_size = size;
 654 
 655         /*
 656          * Allocate virtual window onto ramdisk.
 657          */
 658         mutex_init(&rsp->rd_device_lock, NULL, MUTEX_DRIVER, NULL);
 659         if (addr == 0) {
 660                 rsp->rd_window_obp = 0;
 661                 rsp->rd_window_base = RD_WINDOW_NOT_MAPPED;
 662                 rsp->rd_window_size = PAGESIZE;
 663                 rsp->rd_window_virt = vmem_alloc(heap_arena,
 664                     rsp->rd_window_size, VM_SLEEP);
 665                 if (rsp->rd_window_virt == NULL) {
 666                         goto create_failed;
 667                 }
 668         } else {
 669                 rsp->rd_window_obp = 1;
 670                 rsp->rd_window_base = 0;
 671                 rsp->rd_window_size = size;
 672                 rsp->rd_window_virt = (caddr_t)((ulong_t)addr);
 673         }
 674 
 675         /*
 676          * Allocate physical memory for non-OBP ramdisks.
 677          * Create pseudo block and raw device nodes.
 678          */
 679         if (dip == rd_dip) {
 680                 rsp->rd_npages = btopr(size);
 681                 rsp->rd_ppa = rd_phys_alloc(rsp->rd_npages);
 682                 if (rsp->rd_ppa == NULL) {
 683                         goto create_failed;
 684                 }
 685 
 686                 /*
 687                  * For non-OBP ramdisks the device nodes are:
 688                  *
 689                  *      /devices/pseudo/ramdisk@0:<diskname>
 690                  *      /devices/pseudo/ramdisk@0:<diskname>,raw
 691                  */
 692                 (void) snprintf(namebuf, sizeof (namebuf), "%s",
 693                     rsp->rd_name);
 694                 if (ddi_create_minor_node(dip, namebuf, S_IFBLK, minor,
 695                     DDI_PSEUDO, 0) == DDI_FAILURE) {
 696                         goto create_failed;
 697                 }
 698                 (void) snprintf(namebuf, sizeof (namebuf), "%s,raw",
 699                     rsp->rd_name);
 700                 if (ddi_create_minor_node(dip, namebuf, S_IFCHR, minor,
 701                     DDI_PSEUDO, 0) == DDI_FAILURE) {
 702                         goto create_failed;
 703                 }
 704         } else {
 705                 /*
 706                  * For OBP-created ramdisks the device nodes are:
 707                  *
 708                  *      /devices/ramdisk-<diskname>:a
 709                  *      /devices/ramdisk-<diskname>:a,raw
 710                  */
 711                 if (ddi_create_minor_node(dip, "a", S_IFBLK, minor,
 712                     DDI_PSEUDO, 0) == DDI_FAILURE) {
 713                         goto create_failed;
 714                 }
 715                 if (ddi_create_minor_node(dip, "a,raw", S_IFCHR, minor,
 716                     DDI_PSEUDO, 0) == DDI_FAILURE) {
 717                         goto create_failed;
 718                 }
 719         }
 720 
 721         /*
 722          * Create the "Size" and "Nblocks" properties.
 723          */
 724         fulldev = makedevice(ddi_driver_major(dip), minor);
 725         Size_prop_val = size;
 726         if ((ddi_prop_update_int64(fulldev, dip,
 727             SIZE_PROP_NAME, Size_prop_val)) != DDI_PROP_SUCCESS) {
 728                 goto create_failed;
 729         }
 730         Nblocks_prop_val = size / DEV_BSIZE;
 731         if ((ddi_prop_update_int64(fulldev, dip,
 732             NBLOCKS_PROP_NAME, Nblocks_prop_val)) != DDI_PROP_SUCCESS) {
 733                 goto create_failed;
 734         }
 735 
 736         /*
 737          * Allocate kstat stuff.
 738          */
 739         rsp->rd_kstat = kstat_create(RD_DRIVER_NAME, minor, NULL,
 740             "disk", KSTAT_TYPE_IO, 1, 0);
 741         if (rsp->rd_kstat) {
 742                 mutex_init(&rsp->rd_kstat_lock, NULL,
 743                     MUTEX_DRIVER, NULL);
 744                 rsp->rd_kstat->ks_lock = &rsp->rd_kstat_lock;
 745                 kstat_install(rsp->rd_kstat);
 746         }
 747 
 748         rd_fake_disk_geometry(rsp);
 749 
 750         return (rsp);
 751 
 752 create_failed:
 753         /*
 754          * Cleanup.
 755          */
 756         rd_dealloc_resources(rsp);
 757 
 758         return (NULL);
 759 }
 760 
 761 /*
 762  * Undo what we did in rd_attach, freeing resources and removing things which
 763  * we installed.  The system framework guarantees we are not active with this
 764  * devinfo node in any other entry points at this time.
 765  */
 766 static int
 767 rd_common_detach(dev_info_t *dip)
 768 {
 769         if (dip == rd_dip) {
 770                 /*
 771                  * Pseudo node: can't detach if any pseudo ramdisks exist.
 772                  */
 773                 if (rd_is_busy()) {
 774                         return (DDI_FAILURE);
 775                 }
 776                 ddi_soft_state_free(rd_statep, RD_CTL_MINOR);
 777                 rd_dip = NULL;
 778         } else {
 779                 /*
 780                  * A 'real' ramdisk; find the state and free resources.
 781                  */
 782                 rd_devstate_t   *rsp;
 783 
 784                 if ((rsp = rd_find_dip_state(dip)) != NULL) {
 785                         rd_dealloc_resources(rsp);
 786                 }
 787         }
 788         ddi_remove_minor_node(dip, NULL);
 789 
 790         return (DDI_SUCCESS);
 791 }
 792 
 793 static int
 794 rd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 795 {
 796         char            *name;
 797         rd_existing_t   *ep = NULL;
 798         uint_t          obpaddr = 0, nep, i;
 799         size_t          size = 0;
 800         rd_devstate_t   *rsp;
 801 
 802         switch (cmd) {
 803 
 804         case DDI_ATTACH:
 805                 mutex_enter(&rd_lock);
 806 
 807                 /*
 808                  * For pseudo ramdisk devinfo set up state 0 and :ctl device;
 809                  * else it's an OBP-created ramdisk.
 810                  */
 811                 if (is_pseudo_device(dip)) {
 812                         rd_dip = dip;
 813                         rd_init_tuneables();
 814 
 815                         /*
 816                          * The zeroth minor is reserved for the ramdisk
 817                          * 'control' device.
 818                          */
 819                         if (ddi_soft_state_zalloc(rd_statep, RD_CTL_MINOR) ==
 820                             DDI_FAILURE) {
 821                                 goto attach_failed;
 822                         }
 823                         rsp = ddi_get_soft_state(rd_statep, RD_CTL_MINOR);
 824                         rsp->rd_dip = dip;
 825 
 826                         if (ddi_create_minor_node(dip, RD_CTL_NODE,
 827                             S_IFCHR, 0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
 828                                 goto attach_failed;
 829                         }
 830                 } else {
 831 #ifdef __sparc
 832                         if (bootops_obp_ramdisk_disabled)
 833                                 goto attach_failed;
 834 #endif /* __sparc */
 835 
 836                         RD_STRIP_PREFIX(name, ddi_node_name(dip));
 837 
 838                         if (strlen(name) > RD_NAME_LEN) {
 839                                 cmn_err(CE_CONT,
 840                                     "%s: name too long - ignoring\n", name);
 841                                 goto attach_failed;
 842                         }
 843 
 844                         /*
 845                          * An OBP-created ramdisk must have an 'existing'
 846                          * property; get and check it.
 847                          */
 848                         if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, dip,
 849                             DDI_PROP_DONTPASS, OBP_EXISTING_PROP_NAME,
 850                             (uchar_t **)&ep, &nep) == DDI_SUCCESS) {
 851 
 852                                 if (nep == 0 || (nep % sizeof (*ep)) != 0) {
 853                                         cmn_err(CE_CONT,
 854                                             "%s: " OBP_EXISTING_PROP_NAME
 855                                             " illegal size\n", name);
 856                                         goto attach_failed;
 857                                 }
 858                                 nep /= sizeof (*ep);
 859 
 860                                 /*
 861                                  * Calculate the size of the ramdisk.
 862                                  */
 863                                 for (i = 0; i < nep; ++i) {
 864                                         size += ep[i].size;
 865                                 }
 866                         } else if ((obpaddr = ddi_prop_get_int(DDI_DEV_T_ANY,
 867                             dip, DDI_PROP_DONTPASS, OBP_ADDRESS_PROP_NAME,
 868                             0)) != 0)  {
 869 
 870                                 size = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
 871                                     DDI_PROP_DONTPASS, OBP_SIZE_PROP_NAME, 0);
 872                         } else {
 873                                 cmn_err(CE_CONT, "%s: missing OBP properties\n",
 874                                     name);
 875                                 goto attach_failed;
 876                         }
 877 
 878                         /*
 879                          * Allocate driver resources for the ramdisk.
 880                          */
 881                         if ((rsp = rd_alloc_resources(name, obpaddr, size,
 882                             dip)) == NULL) {
 883                                 goto attach_failed;
 884                         }
 885 
 886                         rsp->rd_existing = ep;
 887                         rsp->rd_nexisting = nep;
 888                 }
 889 
 890                 mutex_exit(&rd_lock);
 891 
 892                 ddi_report_dev(dip);
 893 
 894                 return (DDI_SUCCESS);
 895 
 896         case DDI_RESUME:
 897                 return (DDI_SUCCESS);
 898 
 899         default:
 900                 return (DDI_FAILURE);
 901         }
 902 
 903 attach_failed:
 904         /*
 905          * Use our common detach routine to unallocate any stuff which
 906          * was allocated above.
 907          */
 908         (void) rd_common_detach(dip);
 909         mutex_exit(&rd_lock);
 910 
 911         if (ep != NULL) {
 912                 ddi_prop_free(ep);
 913         }
 914         return (DDI_FAILURE);
 915 }
 916 
 917 static int
 918 rd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 919 {
 920         int     e;
 921 
 922         switch (cmd) {
 923 
 924         case DDI_DETACH:
 925                 mutex_enter(&rd_lock);
 926                 e = rd_common_detach(dip);
 927                 mutex_exit(&rd_lock);
 928 
 929                 return (e);
 930 
 931         case DDI_SUSPEND:
 932                 return (DDI_SUCCESS);
 933 
 934         default:
 935                 return (DDI_FAILURE);
 936         }
 937 }
 938 
 939 /*ARGSUSED*/
 940 static int
 941 rd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 942 {
 943         rd_devstate_t   *rsp;
 944 
 945         switch (infocmd) {
 946         case DDI_INFO_DEVT2DEVINFO:
 947                 if ((rsp = ddi_get_soft_state(rd_statep,
 948                     getminor((dev_t)arg))) != NULL) {
 949                         *result = rsp->rd_dip;
 950                         return (DDI_SUCCESS);
 951                 }
 952                 *result = NULL;
 953                 return (DDI_FAILURE);
 954 
 955         case DDI_INFO_DEVT2INSTANCE:
 956                 if ((rsp = ddi_get_soft_state(rd_statep,
 957                     getminor((dev_t)arg))) != NULL) {
 958                         *result = (void *)(uintptr_t)
 959                             ddi_get_instance(rsp->rd_dip);
 960                         return (DDI_SUCCESS);
 961                 }
 962                 *result = NULL;
 963                 return (DDI_FAILURE);
 964 
 965         default:
 966                 return (DDI_FAILURE);
 967         }
 968 }
 969 
 970 /*ARGSUSED3*/
 971 static int
 972 rd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
 973 {
 974         minor_t         minor;
 975         rd_devstate_t   *rsp;
 976 
 977         mutex_enter(&rd_lock);
 978 
 979         minor = getminor(*devp);
 980         if (minor == RD_CTL_MINOR) {
 981                 /*
 982                  * Master control device; must be opened exclusively.
 983                  */
 984                 if ((flag & FEXCL) != FEXCL || otyp != OTYP_CHR) {
 985                         mutex_exit(&rd_lock);
 986                         return (EINVAL);
 987                 }
 988 
 989                 rsp = ddi_get_soft_state(rd_statep, RD_CTL_MINOR);
 990                 if (rsp == NULL) {
 991                         mutex_exit(&rd_lock);
 992                         return (ENXIO);
 993                 }
 994 
 995                 if (rd_is_open(rsp)) {
 996                         mutex_exit(&rd_lock);
 997                         return (EBUSY);
 998                 }
 999                 (void) rd_opened(rsp, OTYP_CHR);
1000 
1001                 mutex_exit(&rd_lock);
1002 
1003                 return (0);
1004         }
1005 
1006         rsp = ddi_get_soft_state(rd_statep, minor);
1007         if (rsp == NULL) {
1008                 mutex_exit(&rd_lock);
1009                 return (ENXIO);
1010         }
1011 
1012         if (rd_opened(rsp, otyp) == -1) {
1013                 mutex_exit(&rd_lock);
1014                 return (EINVAL);
1015         }
1016 
1017         mutex_exit(&rd_lock);
1018         return (0);
1019 }
1020 
1021 /*ARGSUSED*/
1022 static int
1023 rd_close(dev_t dev, int flag, int otyp, struct cred *credp)
1024 {
1025         minor_t         minor;
1026         rd_devstate_t   *rsp;
1027 
1028         mutex_enter(&rd_lock);
1029 
1030         minor = getminor(dev);
1031 
1032         rsp = ddi_get_soft_state(rd_statep, minor);
1033         if (rsp == NULL) {
1034                 mutex_exit(&rd_lock);
1035                 return (EINVAL);
1036         }
1037 
1038         rd_closed(rsp, otyp);
1039 
1040         mutex_exit(&rd_lock);
1041 
1042         return (0);
1043 }
1044 
1045 static void
1046 rd_minphys(struct buf *bp)
1047 {
1048         if (bp->b_bcount > rd_maxphys) {
1049                 bp->b_bcount = rd_maxphys;
1050         }
1051 }
1052 
1053 static void
1054 rd_rw(rd_devstate_t *rsp, struct buf *bp, offset_t offset, size_t nbytes)
1055 {
1056         int     reading = bp->b_flags & B_READ;
1057         caddr_t buf_addr;
1058 
1059         bp_mapin(bp);
1060         buf_addr = bp->b_un.b_addr;
1061 
1062         while (nbytes > 0) {
1063                 offset_t        off_in_window;
1064                 size_t          rem_in_window, copy_bytes;
1065                 caddr_t         raddr;
1066 
1067                 mutex_enter(&rsp->rd_device_lock);
1068                 rd_map_window(rsp, offset);
1069 
1070                 off_in_window = offset - rsp->rd_window_base;
1071                 rem_in_window = rsp->rd_window_size - off_in_window;
1072 
1073                 raddr = rsp->rd_window_virt + off_in_window;
1074                 copy_bytes = MIN(nbytes, rem_in_window);
1075 
1076                 if (reading) {
1077                         (void) bcopy(raddr, buf_addr, copy_bytes);
1078                 } else {
1079                         (void) bcopy(buf_addr, raddr, copy_bytes);
1080                 }
1081                 mutex_exit(&rsp->rd_device_lock);
1082 
1083                 offset   += copy_bytes;
1084                 buf_addr += copy_bytes;
1085                 nbytes   -= copy_bytes;
1086         }
1087 }
1088 
1089 /*
1090  * On Sparc, this function deals with both pseudo ramdisks and OBP ramdisks.
1091  * In the case where we freed the "bootarchive" ramdisk in bop_free_archive(),
1092  * we stop allowing access to the OBP ramdisks. To do so, we set the
1093  * bootops_obp_ramdisk_disabled flag to true, and we check if the operation
1094  * is for an OBP ramdisk. In this case we indicate an ENXIO error.
1095  */
1096 static int
1097 rd_strategy(struct buf *bp)
1098 {
1099         rd_devstate_t   *rsp;
1100         offset_t        offset;
1101 
1102         rsp = ddi_get_soft_state(rd_statep, getminor(bp->b_edev));
1103         offset = bp->b_blkno * DEV_BSIZE;
1104 
1105 #ifdef __sparc
1106         if (rsp == NULL ||
1107             (bootops_obp_ramdisk_disabled &&
1108             (rsp->rd_dip != rd_dip || rd_dip == NULL))) { /* OBP ramdisk */
1109 #else /* __sparc */
1110         if (rsp == NULL) {
1111 #endif /* __sparc */
1112                 bp->b_error = ENXIO;
1113                 bp->b_flags |= B_ERROR;
1114         } else if (offset >= rsp->rd_size) {
1115                 bp->b_error = EINVAL;
1116                 bp->b_flags |= B_ERROR;
1117         } else {
1118                 size_t  nbytes;
1119 
1120                 if (rsp->rd_kstat) {
1121                         mutex_enter(rsp->rd_kstat->ks_lock);
1122                         kstat_runq_enter(KSTAT_IO_PTR(rsp->rd_kstat));
1123                         mutex_exit(rsp->rd_kstat->ks_lock);
1124                 }
1125 
1126                 nbytes = min(bp->b_bcount, rsp->rd_size - offset);
1127 
1128                 rd_rw(rsp, bp, offset, nbytes);
1129 
1130                 bp->b_resid = bp->b_bcount - nbytes;
1131 
1132                 if (rsp->rd_kstat) {
1133                         kstat_io_t *kioptr;
1134 
1135                         mutex_enter(rsp->rd_kstat->ks_lock);
1136                         kioptr = KSTAT_IO_PTR(rsp->rd_kstat);
1137                         if (bp->b_flags & B_READ) {
1138                                 kioptr->nread += nbytes;
1139                                 kioptr->reads++;
1140                         } else {
1141                                 kioptr->nwritten += nbytes;
1142                                 kioptr->writes++;
1143                         }
1144                         kstat_runq_exit(kioptr);
1145                         mutex_exit(rsp->rd_kstat->ks_lock);
1146                 }
1147         }
1148 
1149         biodone(bp);
1150         return (0);
1151 }
1152 
1153 /*ARGSUSED*/
1154 static int
1155 rd_read(dev_t dev, struct uio *uiop, cred_t *credp)
1156 {
1157         rd_devstate_t   *rsp;
1158 
1159         rsp = ddi_get_soft_state(rd_statep, getminor(dev));
1160 
1161         if (uiop->uio_offset >= rsp->rd_size)
1162                 return (EINVAL);
1163 
1164         return (physio(rd_strategy, NULL, dev, B_READ, rd_minphys, uiop));
1165 }
1166 
1167 /*ARGSUSED*/
1168 static int
1169 rd_write(dev_t dev, register struct uio *uiop, cred_t *credp)
1170 {
1171         rd_devstate_t   *rsp;
1172 
1173         rsp = ddi_get_soft_state(rd_statep, getminor(dev));
1174 
1175         if (uiop->uio_offset >= rsp->rd_size)
1176                 return (EINVAL);
1177 
1178         return (physio(rd_strategy, NULL, dev, B_WRITE, rd_minphys, uiop));
1179 }
1180 
1181 /*ARGSUSED*/
1182 static int
1183 rd_create_disk(dev_t dev, struct rd_ioctl *urip, int mode, int *rvalp)
1184 {
1185         struct rd_ioctl kri;
1186         size_t          size;
1187         rd_devstate_t   *rsp;
1188 
1189         if (ddi_copyin(urip, &kri, sizeof (kri), mode) == -1) {
1190                 return (EFAULT);
1191         }
1192 
1193         kri.ri_name[RD_NAME_LEN] = '\0';
1194 
1195         size = kri.ri_size;
1196         if (size == 0) {
1197                 return (EINVAL);
1198         }
1199         size = ptob(btopr(size));
1200 
1201         mutex_enter(&rd_lock);
1202 
1203         if (rd_find_named_disk(kri.ri_name) != NULL) {
1204                 mutex_exit(&rd_lock);
1205                 return (EEXIST);
1206         }
1207 
1208         rsp = rd_alloc_resources(kri.ri_name, 0, size, rd_dip);
1209         if (rsp == NULL) {
1210                 mutex_exit(&rd_lock);
1211                 return (EAGAIN);
1212         }
1213 
1214         mutex_exit(&rd_lock);
1215 
1216         return (ddi_copyout(&kri, urip, sizeof (kri), mode) == -1 ? EFAULT : 0);
1217 }
1218 
1219 /*ARGSUSED*/
1220 static int
1221 rd_delete_disk(dev_t dev, struct rd_ioctl *urip, int mode)
1222 {
1223         struct rd_ioctl kri;
1224         rd_devstate_t   *rsp;
1225 
1226         if (ddi_copyin(urip, &kri, sizeof (kri), mode) == -1) {
1227                 return (EFAULT);
1228         }
1229 
1230         kri.ri_name[RD_NAME_LEN] = '\0';
1231 
1232         mutex_enter(&rd_lock);
1233 
1234         rsp = rd_find_named_disk(kri.ri_name);
1235         if (rsp == NULL || rsp->rd_dip != rd_dip) {
1236                 mutex_exit(&rd_lock);
1237                 return (EINVAL);
1238         }
1239         if (rd_is_open(rsp)) {
1240                 mutex_exit(&rd_lock);
1241                 return (EBUSY);
1242         }
1243 
1244         rd_dealloc_resources(rsp);
1245 
1246         mutex_exit(&rd_lock);
1247 
1248         return (0);
1249 }
1250 
1251 /*ARGSUSED*/
1252 static int
1253 rd_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
1254 {
1255         minor_t         minor;
1256         int             error;
1257         enum dkio_state dkstate;
1258         rd_devstate_t   *rsp;
1259 
1260         minor = getminor(dev);
1261 
1262         /*
1263          * Ramdisk ioctls only apply to the master device.
1264          */
1265         if (minor == RD_CTL_MINOR) {
1266                 struct rd_ioctl *rip = (struct rd_ioctl *)arg;
1267 
1268                 /*
1269                  * The query commands only need read-access - i.e., normal
1270                  * users are allowed to do those on the controlling device
1271                  * as long as they can open it read-only.
1272                  */
1273                 switch (cmd) {
1274                 case RD_CREATE_DISK:
1275                         if ((mode & FWRITE) == 0)
1276                                 return (EPERM);
1277                         return (rd_create_disk(dev, rip, mode, rvalp));
1278 
1279                 case RD_DELETE_DISK:
1280                         if ((mode & FWRITE) == 0)
1281                                 return (EPERM);
1282                         return (rd_delete_disk(dev, rip, mode));
1283 
1284                 default:
1285                         return (EINVAL);
1286                 }
1287         }
1288 
1289         rsp = ddi_get_soft_state(rd_statep, minor);
1290         if (rsp == NULL) {
1291                 return (ENXIO);
1292         }
1293 
1294         /*
1295          * These are for faking out utilities like newfs.
1296          */
1297         switch (cmd) {
1298         case DKIOCGVTOC:
1299                 switch (ddi_model_convert_from(mode & FMODELS)) {
1300                 case DDI_MODEL_ILP32: {
1301                         struct vtoc32 vtoc32;
1302 
1303                         vtoctovtoc32(rsp->rd_vtoc, vtoc32);
1304                         if (ddi_copyout(&vtoc32, (void *)arg,
1305                             sizeof (struct vtoc32), mode))
1306                                 return (EFAULT);
1307                         }
1308                         break;
1309 
1310                 case DDI_MODEL_NONE:
1311                         if (ddi_copyout(&rsp->rd_vtoc, (void *)arg,
1312                             sizeof (struct vtoc), mode))
1313                                 return (EFAULT);
1314                         break;
1315                 }
1316                 return (0);
1317         case DKIOCINFO:
1318                 error = ddi_copyout(&rsp->rd_ci, (void *)arg,
1319                     sizeof (struct dk_cinfo), mode);
1320                 if (error)
1321                         return (EFAULT);
1322                 return (0);
1323         case DKIOCG_VIRTGEOM:
1324         case DKIOCG_PHYGEOM:
1325         case DKIOCGGEOM:
1326                 error = ddi_copyout(&rsp->rd_dkg, (void *)arg,
1327                     sizeof (struct dk_geom), mode);
1328                 if (error)
1329                         return (EFAULT);
1330                 return (0);
1331         case DKIOCSTATE:
1332                 /* the file is always there */
1333                 dkstate = DKIO_INSERTED;
1334                 error = ddi_copyout(&dkstate, (void *)arg,
1335                     sizeof (enum dkio_state), mode);
1336                 if (error)
1337                         return (EFAULT);
1338                 return (0);
1339         default:
1340                 return (ENOTTY);
1341         }
1342 }
1343 
1344 
1345 static struct cb_ops rd_cb_ops = {
1346         rd_open,
1347         rd_close,
1348         rd_strategy,
1349         nodev,
1350         nodev,          /* dump */
1351         rd_read,
1352         rd_write,
1353         rd_ioctl,
1354         nodev,          /* devmap */
1355         nodev,          /* mmap */
1356         nodev,          /* segmap */
1357         nochpoll,       /* poll */
1358         ddi_prop_op,
1359         NULL,
1360         D_NEW | D_MP
1361 };
1362 
1363 static struct dev_ops rd_ops = {
1364         DEVO_REV,
1365         0,
1366         rd_getinfo,
1367         nulldev,        /* identify */
1368         nulldev,        /* probe */
1369         rd_attach,
1370         rd_detach,
1371         nodev,          /* reset */
1372         &rd_cb_ops,
1373         (struct bus_ops *)0,
1374         NULL,
1375         ddi_quiesce_not_needed,         /* quiesce */
1376 };
1377 
1378 
1379 extern struct mod_ops mod_driverops;
1380 
1381 static struct modldrv modldrv = {
1382         &mod_driverops,
1383         "ramdisk driver",
1384         &rd_ops
1385 };
1386 
1387 static struct modlinkage modlinkage = {
1388         MODREV_1,
1389         { &modldrv, NULL }
1390 };
1391 
1392 int
1393 _init(void)
1394 {
1395         int e;
1396 
1397         if ((e = ddi_soft_state_init(&rd_statep,
1398             sizeof (rd_devstate_t), 0)) != 0) {
1399                 return (e);
1400         }
1401 
1402         mutex_init(&rd_lock, NULL, MUTEX_DRIVER, NULL);
1403 
1404         if ((e = mod_install(&modlinkage)) != 0)  {
1405                 mutex_destroy(&rd_lock);
1406                 ddi_soft_state_fini(&rd_statep);
1407         }
1408 
1409         return (e);
1410 }
1411 
1412 int
1413 _fini(void)
1414 {
1415         int e;
1416 
1417         if ((e = mod_remove(&modlinkage)) != 0)  {
1418                 return (e);
1419         }
1420 
1421         ddi_soft_state_fini(&rd_statep);
1422         mutex_destroy(&rd_lock);
1423 
1424         return (e);
1425 }
1426 
1427 int
1428 _info(struct modinfo *modinfop)
1429 {
1430         return (mod_info(&modlinkage, modinfop));
1431 }