xref: /illumos-gate/usr/src/uts/common/io/ramdisk.c (revision 51396a8ee7fb52fe0ab33bfe7b4f495ad431904a)
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, 0) == 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,
1390 	0
1391 };
1392 
1393 int
1394 _init(void)
1395 {
1396 	int e;
1397 
1398 	if ((e = ddi_soft_state_init(&rd_statep,
1399 	    sizeof (rd_devstate_t), 0)) != 0) {
1400 		return (e);
1401 	}
1402 
1403 	mutex_init(&rd_lock, NULL, MUTEX_DRIVER, NULL);
1404 
1405 	if ((e = mod_install(&modlinkage)) != 0)  {
1406 		mutex_destroy(&rd_lock);
1407 		ddi_soft_state_fini(&rd_statep);
1408 	}
1409 
1410 	return (e);
1411 }
1412 
1413 int
1414 _fini(void)
1415 {
1416 	int e;
1417 
1418 	if ((e = mod_remove(&modlinkage)) != 0)  {
1419 		return (e);
1420 	}
1421 
1422 	ddi_soft_state_fini(&rd_statep);
1423 	mutex_destroy(&rd_lock);
1424 
1425 	return (e);
1426 }
1427 
1428 int
1429 _info(struct modinfo *modinfop)
1430 {
1431 	return (mod_info(&modlinkage, modinfop));
1432 }
1433