1/* 2 * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * Copyright (c) 1988 University of Utah. 30 * Copyright (c) 1990, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * the Systems Programming Group of the University of Utah Computer 35 * Science Department. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. All advertising materials mentioning features or use of this software 46 * must display the following acknowledgement: 47 * This product includes software developed by the University of 48 * California, Berkeley and its contributors. 49 * 4. Neither the name of the University nor the names of its contributors 50 * may be used to endorse or promote products derived from this software 51 * without specific prior written permission. 52 * 53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * SUCH DAMAGE. 64 * 65 * from: Utah Hdr: vn.c 1.13 94/04/02 66 * 67 * from: @(#)vn.c 8.6 (Berkeley) 4/1/94 68 * $FreeBSD: src/sys/dev/vn/vn.c,v 1.105.2.4 2001/11/18 07:11:00 dillon Exp $ 69 */ 70 71/* 72 * RAM disk driver. 73 * 74 * Block interface to a ramdisk. 75 * 76 */ 77 78#include <sys/param.h> 79#include <sys/kernel.h> 80#include <sys/mount.h> 81#include <sys/namei.h> 82#include <sys/proc.h> 83#include <sys/buf.h> 84#include <sys/malloc.h> 85#include <sys/mount.h> 86#include <sys/fcntl.h> 87#include <sys/conf.h> 88#include <sys/disk.h> 89#include <sys/stat.h> 90#include <sys/vm.h> 91#include <sys/uio_internal.h> 92#include <libkern/libkern.h> 93 94#include <vm/pmap.h> 95#include <vm/vm_pager.h> 96#include <mach/memory_object_types.h> 97#include <kern/debug.h> 98 99#include <miscfs/devfs/devfs.h> 100 101 102void mdevinit(int the_cnt); 103 104static open_close_fcn_t mdevopen; 105static open_close_fcn_t mdevclose; 106static psize_fcn_t mdevsize; 107static strategy_fcn_t mdevstrategy; 108static int mdevbioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); 109static int mdevcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p); 110static int mdevrw(dev_t dev, struct uio *uio, int ioflag); 111#ifdef CONFIG_MEMDEV_INSECURE 112static char * nonspace(char *pos, char *end); 113static char * getspace(char *pos, char *end); 114static char * cvtnum(char *pos, char *end, unsigned int *num); 115#endif /* CONFIG_MEMDEV_INSECURE */ 116 117extern void bcopy_phys(addr64_t from, addr64_t to, vm_size_t bytes); 118extern void mapping_set_mod(ppnum_t pn); 119extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); 120 121 122/* 123 * cdevsw 124 * D_DISK we want to look like a disk 125 * D_CANFREE We support B_FREEBUF 126 */ 127 128static struct bdevsw mdevbdevsw = { 129 /* open */ mdevopen, 130 /* close */ mdevclose, 131 /* strategy */ mdevstrategy, 132 /* ioctl */ mdevbioctl, 133 /* dump */ eno_dump, 134 /* psize */ mdevsize, 135 /* flags */ D_DISK, 136}; 137 138static struct cdevsw mdevcdevsw = { 139 /* open */ mdevopen, 140 /* close */ mdevclose, 141 /* read */ mdevrw, 142 /* write */ mdevrw, 143 /* ioctl */ mdevcioctl, 144 /* stop */ eno_stop, 145 /* reset */ eno_reset, 146 /* ttys */ NULL, 147 /* select */ eno_select, 148 /* mmap */ eno_mmap, 149 /* strategy */ eno_strat, 150 /* getc */ eno_getc, 151 /* putc */ eno_putc, 152 /* flags */ D_DISK, 153}; 154 155struct mdev { 156 vm_offset_t mdBase; /* file size in bytes */ 157 uint32_t mdSize; /* file size in bytes */ 158 int mdFlags; /* flags */ 159 int mdSecsize; /* sector size */ 160 int mdBDev; /* Block device number */ 161 int mdCDev; /* Character device number */ 162 void * mdbdevb; 163 void * mdcdevb; 164} mdev[16]; 165 166/* mdFlags */ 167#define mdInited 0x01 /* This device defined */ 168#define mdRO 0x02 /* This device is read-only */ 169#define mdPhys 0x04 /* This device is in physical memory */ 170 171int mdevBMajor = -1; 172int mdevCMajor = -1; 173 174static int mdevioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p, int is_char); 175dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys); 176dev_t mdevlookup(int devid); 177void mdevremoveall(void); 178 179static int mdevclose(__unused dev_t dev, __unused int flags, 180 __unused int devtype, __unused struct proc *p) { 181 182 return (0); 183} 184 185static int mdevopen(dev_t dev, int flags, __unused int devtype, __unused struct proc *p) { 186 187 int devid; 188 189 devid = minor(dev); /* Get minor device number */ 190 191 if (devid > 16) return (ENXIO); /* Not valid */ 192 193 if ((flags & FWRITE) && (mdev[devid].mdFlags & mdRO)) return (EACCES); /* Currently mounted RO */ 194 195 return(0); 196} 197 198static int mdevrw(dev_t dev, struct uio *uio, __unused int ioflag) { 199 int status; 200 addr64_t mdata; 201 int devid; 202 enum uio_seg saveflag; 203 204 devid = minor(dev); /* Get minor device number */ 205 206 if (devid > 16) return (ENXIO); /* Not valid */ 207 if (!(mdev[devid].mdFlags & mdInited)) return (ENXIO); /* Have we actually been defined yet? */ 208 209 mdata = ((addr64_t)mdev[devid].mdBase << 12) + uio->uio_offset; /* Point to the area in "file" */ 210 211 saveflag = uio->uio_segflg; /* Remember what the request is */ 212#if LP64_DEBUG 213 if (IS_VALID_UIO_SEGFLG(uio->uio_segflg) == 0) { 214 panic("mdevrw - invalid uio_segflg\n"); 215 } 216#endif /* LP64_DEBUG */ 217 /* Make sure we are moving from physical ram if physical device */ 218 if (mdev[devid].mdFlags & mdPhys) { 219 if (uio->uio_segflg == UIO_USERSPACE64) 220 uio->uio_segflg = UIO_PHYS_USERSPACE64; 221 else if (uio->uio_segflg == UIO_USERSPACE32) 222 uio->uio_segflg = UIO_PHYS_USERSPACE32; 223 else 224 uio->uio_segflg = UIO_PHYS_USERSPACE; 225 } 226 status = uiomove64(mdata, uio_resid(uio), uio); /* Move the data */ 227 uio->uio_segflg = saveflag; /* Restore the flag */ 228 229 return (status); 230} 231 232static void mdevstrategy(struct buf *bp) { 233 unsigned int left, lop, csize; 234 vm_offset_t vaddr, blkoff; 235 int devid; 236 addr64_t paddr, fvaddr; 237 ppnum_t pp; 238 239 devid = minor(buf_device(bp)); /* Get minor device number */ 240 241 if ((mdev[devid].mdFlags & mdInited) == 0) { /* Have we actually been defined yet? */ 242 buf_seterror(bp, ENXIO); 243 buf_biodone(bp); 244 return; 245 } 246 247 buf_setresid(bp, buf_count(bp)); /* Set byte count */ 248 249 blkoff = buf_blkno(bp) * mdev[devid].mdSecsize; /* Get offset into file */ 250 251/* 252 * Note that reading past end is an error, but reading at end is an EOF. For these 253 * we just return with resid == count. 254 */ 255 256 if (blkoff >= (mdev[devid].mdSize << 12)) { /* Are they trying to read/write at/after end? */ 257 if(blkoff != (mdev[devid].mdSize << 12)) { /* Are we trying to read after EOF? */ 258 buf_seterror(bp, EINVAL); /* Yeah, this is an error */ 259 } 260 buf_biodone(bp); /* Return */ 261 return; 262 } 263 264 if ((blkoff + buf_count(bp)) > (mdev[devid].mdSize << 12)) { /* Will this read go past end? */ 265 buf_setcount(bp, ((mdev[devid].mdSize << 12) - blkoff)); /* Yes, trim to max */ 266 } 267 /* 268 * make sure the buffer's data area is 269 * accessible 270 */ 271 if (buf_map(bp, (caddr_t *)&vaddr)) 272 panic("ramstrategy: buf_map failed\n"); 273 274 fvaddr = (mdev[devid].mdBase << 12) + blkoff; /* Point to offset into ram disk */ 275 276 if (buf_flags(bp) & B_READ) { /* Is this a read? */ 277 if(!(mdev[devid].mdFlags & mdPhys)) { /* Physical mapped disk? */ 278 bcopy((void *)((uintptr_t)fvaddr), 279 (void *)vaddr, (size_t)buf_count(bp)); /* This is virtual, just get the data */ 280 } 281 else { 282 left = buf_count(bp); /* Init the amount left to copy */ 283 while(left) { /* Go until it is all copied */ 284 285 lop = min((4096 - (vaddr & 4095)), (4096 - (fvaddr & 4095))); /* Get smallest amount left on sink and source */ 286 csize = min(lop, left); /* Don't move more than we need to */ 287 288 pp = pmap_find_phys(kernel_pmap, (addr64_t)((unsigned int)vaddr)); /* Get the sink physical address */ 289 if(!pp) { /* Not found, what gives? */ 290 panic("mdevstrategy: sink address %016llX not mapped\n", (addr64_t)((unsigned int)vaddr)); 291 } 292 paddr = (addr64_t)(((addr64_t)pp << 12) | (addr64_t)(vaddr & 4095)); /* Get actual address */ 293 bcopy_phys(fvaddr, paddr, csize); /* Copy this on in */ 294 mapping_set_mod(paddr >> 12); /* Make sure we know that it is modified */ 295 296 left = left - csize; /* Calculate what is left */ 297 vaddr = vaddr + csize; /* Move to next sink address */ 298 fvaddr = fvaddr + csize; /* Bump to next physical address */ 299 } 300 } 301 } 302 else { /* This is a write */ 303 if(!(mdev[devid].mdFlags & mdPhys)) { /* Physical mapped disk? */ 304 bcopy((void *)vaddr, (void *)((uintptr_t)fvaddr), 305 (size_t)buf_count(bp)); /* This is virtual, just put the data */ 306 } 307 else { 308 left = buf_count(bp); /* Init the amount left to copy */ 309 while(left) { /* Go until it is all copied */ 310 311 lop = min((4096 - (vaddr & 4095)), (4096 - (fvaddr & 4095))); /* Get smallest amount left on sink and source */ 312 csize = min(lop, left); /* Don't move more than we need to */ 313 314 pp = pmap_find_phys(kernel_pmap, (addr64_t)((unsigned int)vaddr)); /* Get the source physical address */ 315 if(!pp) { /* Not found, what gives? */ 316 panic("mdevstrategy: source address %016llX not mapped\n", (addr64_t)((unsigned int)vaddr)); 317 } 318 paddr = (addr64_t)(((addr64_t)pp << 12) | (addr64_t)(vaddr & 4095)); /* Get actual address */ 319 320 bcopy_phys(paddr, fvaddr, csize); /* Move this on out */ 321 322 left = left - csize; /* Calculate what is left */ 323 vaddr = vaddr + csize; /* Move to next sink address */ 324 fvaddr = fvaddr + csize; /* Bump to next physical address */ 325 } 326 } 327 } 328 /* 329 * buf_unmap takes care of all the cases 330 * it will unmap the buffer from kernel 331 * virtual space if that was the state 332 * when we mapped it. 333 */ 334 buf_unmap(bp); 335 336 buf_setresid(bp, 0); /* Nothing more to do */ 337 buf_biodone(bp); /* Say we've finished */ 338} 339 340static int mdevbioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { 341 return (mdevioctl(dev, cmd, data, flag, p, 0)); 342} 343 344static int mdevcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { 345 return (mdevioctl(dev, cmd, data, flag, p, 1)); 346} 347 348static int mdevioctl(dev_t dev, u_long cmd, caddr_t data, __unused int flag, 349 struct proc *p, int is_char) { 350 int error; 351 u_long *f; 352 u_int64_t *o; 353 int devid; 354 355 devid = minor(dev); /* Get minor device number */ 356 357 if (devid > 16) return (ENXIO); /* Not valid */ 358 359 error = proc_suser(p); /* Are we superman? */ 360 if (error) return (error); /* Nope... */ 361 362 f = (u_long*)data; 363 o = (u_int64_t *)data; 364 365 switch (cmd) { 366 367 case DKIOCGETMAXBLOCKCOUNTREAD: 368 *o = 32; 369 break; 370 371 case DKIOCGETMAXBLOCKCOUNTWRITE: 372 *o = 32; 373 break; 374 375 case DKIOCGETMAXSEGMENTCOUNTREAD: 376 *o = 32; 377 break; 378 379 case DKIOCGETMAXSEGMENTCOUNTWRITE: 380 *o = 32; 381 break; 382 383 case DKIOCGETBLOCKSIZE: 384 *f = mdev[devid].mdSecsize; 385 break; 386 387 case DKIOCSETBLOCKSIZE: 388 if (is_char) return (ENODEV); /* We can only do this for a block */ 389 390 if (*f < DEV_BSIZE) return (EINVAL); /* Too short? */ 391 392 mdev[devid].mdSecsize = *f; /* set the new block size */ 393 break; 394 395 case DKIOCISWRITABLE: 396 *f = 1; 397 break; 398 399 case DKIOCGETBLOCKCOUNT32: 400 if(!(mdev[devid].mdFlags & mdInited)) return (ENXIO); 401 *f = ((mdev[devid].mdSize << 12) + mdev[devid].mdSecsize - 1) / mdev[devid].mdSecsize; 402 break; 403 404 case DKIOCGETBLOCKCOUNT: 405 if(!(mdev[devid].mdFlags & mdInited)) return (ENXIO); 406 *o = ((mdev[devid].mdSize << 12) + mdev[devid].mdSecsize - 1) / mdev[devid].mdSecsize; 407 break; 408 409 default: 410 error = ENOTTY; 411 break; 412 } 413 return(error); 414} 415 416 417static int mdevsize(dev_t dev) { 418 419 int devid; 420 421 devid = minor(dev); /* Get minor device number */ 422 if (devid > 16) return (ENXIO); /* Not valid */ 423 424 if ((mdev[devid].mdFlags & mdInited) == 0) return(-1); /* Not inited yet */ 425 426 return(mdev[devid].mdSecsize); 427} 428 429#include <pexpert/pexpert.h> 430 431void mdevinit(__unused int the_cnt) { 432 433#ifdef CONFIG_MEMDEV_INSECURE 434 435 int devid, phys; 436 ppnum_t base; 437 unsigned int size; 438 char *ba, *lp; 439 dev_t dev; 440 441 ba = PE_boot_args(); /* Get the boot arguments */ 442 lp = ba + 256; /* Point to the end */ 443 444 while(1) { /* Step through, looking for our keywords */ 445 phys = 0; /* Assume virtual memory device */ 446 ba = nonspace(ba, lp); /* Find non-space */ 447 if(ba >= lp) return; /* We are done if no more... */ 448 if(((ba[0] != 'v') && (ba[0] != 'p')) 449 || (ba[1] != 'm') || (ba[2] != 'd') || (ba[4] != '=') 450 || (ba[3] < '0') || (ba[3] > 'f') 451 || ((ba[3] > '9') && (ba[3] < 'a'))) { /* Is this of form "vmdx=" or "pmdx=" where x is hex digit? */ 452 453 ba = getspace(ba, lp); /* Find next white space or end */ 454 continue; /* Start looking for the next one */ 455 } 456 457 if(ba[0] == 'p') phys = 1; /* Set physical memory disk */ 458 459 devid = ba[3] & 0xF; /* Assume digit */ 460 if(ba[3] > '9') devid += 9; /* Adjust for hex digits */ 461 462 ba = &ba[5]; /* Step past keyword */ 463 ba = cvtnum(ba, lp, &base); /* Convert base of memory disk */ 464 if(ba >= lp) return; /* Malformed one at the end, leave */ 465 if(ba[0] != '.') continue; /* If not length separater, try next... */ 466 if(base & 0xFFF) continue; /* Only allow page aligned stuff */ 467 468 ba++; /* Step past '.' */ 469 ba = cvtnum(ba, lp, &size); /* Try to convert it */ 470 if(!size || (size & 0xFFF)) continue; /* Allow only non-zer page size multiples */ 471 if(ba < lp) { /* If we are not at end, check end character */ 472 if((ba[0] != ' ') && (ba[0] != 0)) continue; /* End must be null or space */ 473 } 474 475 dev = mdevadd(devid, base >> 12, size >> 12, phys); /* Go add the device */ 476 } 477 478#endif /* CONFIG_MEMDEV_INSECURE */ 479 return; 480 481} 482 483#ifdef CONFIG_MEMDEV_INSECURE 484char *nonspace(char *pos, char *end) { /* Find next non-space in string */ 485 486 if(pos >= end) return end; /* Don't go past end */ 487 if(pos[0] == 0) return end; /* If at null, make end */ 488 489 while(1) { /* Keep going */ 490 if(pos[0] != ' ') return pos; /* Leave if we found one */ 491 pos++; /* Stop */ 492 if(pos >= end) return end; /* Quit if we run off end */ 493 } 494} 495 496char *getspace(char *pos, char *end) { /* Find next non-space in string */ 497 498 while(1) { /* Keep going */ 499 if(pos >= end) return end; /* Don't go past end */ 500 if(pos[0] == 0) return end; /* Leave if we hit null */ 501 if(pos[0] == ' ') return pos; /* Leave if we found one */ 502 pos++; /* Stop */ 503 } 504} 505 506char *cvtnum(char *pos, char *end, unsigned int *num) { /* Convert to a number */ 507 508 int rad, dig; 509 510 *num = 0; /* Set answer to 0 to start */ 511 rad = 10; 512 513 if(pos >= end) return end; /* Don't go past end */ 514 if(pos[0] == 0) return end; /* If at null, make end */ 515 516 if(pos[0] == '0' && ((pos[1] == 'x') || (pos[1] == 'x'))) { /* A hex constant? */ 517 rad = 16; 518 pos += 2; /* Point to the number */ 519 } 520 521 while(1) { /* Convert it */ 522 523 if(pos >= end) return end; /* Don't go past end */ 524 if(pos[0] == 0) return end; /* If at null, make end */ 525 if(pos[0] < '0') return pos; /* Leave if non-digit */ 526 dig = pos[0] & 0xF; /* Extract digit */ 527 if(pos[0] > '9') { /* Is it bigger than 9? */ 528 if(rad == 10) return pos; /* Leave if not base 10 */ 529 if(!(((pos[0] >= 'A') && (pos[0] <= 'F')) 530 || ((pos[0] >= 'a') && (pos[0] <= 'f')))) return pos; /* Leave if bogus char */ 531 dig = dig + 9; /* Adjust for character */ 532 } 533 *num = (*num * rad) + dig; /* Accumulate the number */ 534 pos++; /* Step on */ 535 } 536} 537#endif /* CONFIG_MEMDEV_INSECURE */ 538 539dev_t mdevadd(int devid, ppnum_t base, unsigned int size, int phys) { 540 541 int i; 542 543 if(devid < 0) { 544 545 devid = -1; 546 for(i = 0; i < 16; i++) { /* Search all known memory devices */ 547 if(!(mdev[i].mdFlags & mdInited)) { /* Is this a free one? */ 548 if(devid < 0)devid = i; /* Remember first free one */ 549 continue; /* Skip check */ 550 } 551 if(!(((base + size -1 ) < mdev[i].mdBase) || ((mdev[i].mdBase + mdev[i].mdSize - 1) < base))) { /* Is there any overlap? */ 552 panic("mdevadd: attempt to add overlapping memory device at %08X-%08X\n", mdev[i].mdBase, mdev[i].mdBase + mdev[i].mdSize - 1); 553 } 554 } 555 if(devid < 0) { /* Do we have free slots? */ 556 panic("mdevadd: attempt to add more than 16 memory devices\n"); 557 } 558 } 559 else { 560 if(devid >= 16) { /* Giving us something bogus? */ 561 panic("mdevadd: attempt to explicitly add a bogus memory device: %08X\n", devid); 562 } 563 if(mdev[devid].mdFlags &mdInited) { /* Already there? */ 564 panic("mdevadd: attempt to explicitly add a previously defined memory device: %08X\n", devid); 565 } 566 } 567 568 if(mdevBMajor < 0) { /* Have we gotten a major number yet? */ 569 mdevBMajor = bdevsw_add(-1, &mdevbdevsw); /* Add to the table and figure out a major number */ 570 if (mdevBMajor < 0) { 571 printf("mdevadd: error - bdevsw_add() returned %d\n", mdevBMajor); 572 return -1; 573 } 574 } 575 576 if(mdevCMajor < 0) { /* Have we gotten a major number yet? */ 577 mdevCMajor = cdevsw_add_with_bdev(-1, &mdevcdevsw, mdevBMajor); /* Add to the table and figure out a major number */ 578 if (mdevCMajor < 0) { 579 printf("ramdevice_init: error - cdevsw_add() returned %d\n", mdevCMajor); 580 return -1; 581 } 582 } 583 584 mdev[devid].mdBDev = makedev(mdevBMajor, devid); /* Get the device number */ 585 mdev[devid].mdbdevb = devfs_make_node(mdev[devid].mdBDev, DEVFS_BLOCK, /* Make the node */ 586 UID_ROOT, GID_OPERATOR, 587 0600, "md%d", devid); 588 if (mdev[devid].mdbdevb == NULL) { /* Did we make one? */ 589 printf("mdevadd: devfs_make_node for block failed!\n"); 590 return -1; /* Nope... */ 591 } 592 593 mdev[devid].mdCDev = makedev(mdevCMajor, devid); /* Get the device number */ 594 mdev[devid].mdcdevb = devfs_make_node(mdev[devid].mdCDev, DEVFS_CHAR, /* Make the node */ 595 UID_ROOT, GID_OPERATOR, 596 0600, "rmd%d", devid); 597 if (mdev[devid].mdcdevb == NULL) { /* Did we make one? */ 598 printf("mdevadd: devfs_make_node for character failed!\n"); 599 return -1; /* Nope... */ 600 } 601 602 mdev[devid].mdBase = base; /* Set the base address of ram disk */ 603 mdev[devid].mdSize = size; /* Set the length of the ram disk */ 604 mdev[devid].mdSecsize = DEV_BSIZE; /* Set starting block size */ 605 if(phys) mdev[devid].mdFlags |= mdPhys; /* Show that we are in physical memory */ 606 mdev[devid].mdFlags |= mdInited; /* Show we are all set up */ 607 printf("Added memory device md%x/rmd%x (%08X/%08X) at %08X for %08X\n", 608 devid, devid, mdev[devid].mdBDev, mdev[devid].mdCDev, base << 12, size << 12); 609 return mdev[devid].mdBDev; 610} 611 612 613dev_t mdevlookup(int devid) { 614 615 if((devid < 0) || (devid > 15)) return -1; /* Filter any bogus requests */ 616 if(!(mdev[devid].mdFlags & mdInited)) return -1; /* This one hasn't been defined */ 617 return mdev[devid].mdBDev; /* Return the device number */ 618} 619 620void mdevremoveall(void) { 621 622 int i; 623 624 for(i = 0; i < 16; i++) { 625 if(!(mdev[i].mdFlags & mdInited)) continue; /* Ignore unused mdevs */ 626 627 devfs_remove(mdev[i].mdbdevb); /* Remove the block device */ 628 devfs_remove(mdev[i].mdcdevb); /* Remove the character device */ 629 630 mdev[i].mdBase = 0; /* Clear the mdev's storage */ 631 mdev[i].mdSize = 0; 632 mdev[i].mdSecsize = 0; 633 mdev[i].mdFlags = 0; 634 mdev[i].mdBDev = 0; 635 mdev[i].mdCDev = 0; 636 mdev[i].mdbdevb = 0; 637 mdev[i].mdcdevb = 0; 638 } 639} 640