/* * Ram Disk device for 68000/XENIX * By Roy A. Neese, Paul Chamberlain, John Elliott IV and Dennis Young * 21 Jan 1988 Copyright Tandy Corp. 1987, 1988 * * The following driver has been written for XENIX. Without any * kernel modifications the ramswap device will have to start at * the 2 Meg boundary, for the 1.3.* version of XENIX. This is due * to XENIX trying to grab all available memory for User space. XENIX * does a test on 4K boundaries to determine how much user memory * there is. If the board could be addressed starting at 1.5Meg then * this will take care of the problem. * The 3.1.* versions of XENIX will only grab the 1 meg of memory thereby * getting rid of this problem. XENIX 3.2 and later once again try to * claim all available memory, due to the MMU project. * * STEP 1 >------------------------------------------------------------------- * * To make the ramswapper, type in the following: * * If you are using 3.2 or later then: * cc -O -K -c ramswap.c * * If you are using any other 3.x then: * cc -O -K -DV31 -c ramswap.c * * If you are using 1.3.x then: * cc -O -K -DV7 -c ramswap.c * * Do the following regardless of the version of Xenix: * ar rv /usr/sys/io/lib_io ramswap.o * ranlib /usr/sys/io/lib_io * * STEP 2 >------------------------------------------------------------------- * * You will need to use 'mknod' to make the new devices. To do this, * type in the following commands. * * mknod ra11 b 2 0 ; mknod rra11 c 9 0 * mknod ra12 b 2 1 ; mknod rra12 c 9 1 * mknod ra13 b 2 2 ; mknod rra13 c 9 2 * mknod ra14 b 2 3 ; mknod rra14 c 9 3 * mknod ra21 b 2 4 ; mknod rra21 c 9 4 * mknod ra22 b 2 5 ; mknod rra22 c 9 5 * mknod ra23 b 2 6 ; mknod rra23 c 9 6 * mknod ra31 b 2 7 ; mknod rra31 c 9 7 * mknod ra32 b 2 8 ; mknod rra32 c 9 8 * mknod ra41 b 2 9 ; mknod rra41 c 9 9 * * STEP 3 >------------------------------------------------------------------- * * You need to move the old /dev/swap to /dev/swap.old and link the * new device to /dev/swap, in order for certain things to work right, * like 'ps'. * Type "ln device swap" and press enter. The device will be a ramswap * device, not the hard disk device. * * STEP 4 >------------------------------------------------------------------- * * The files /usr/sys/conf/master will have to have the following * entry added to it. * * name vsiz msk typ hndlr na bmaj cmaj # na vec1 vec2 vec3 vec4 * 1 2 3 4 5 6 7 8 9 10 11 12 13 14 *ramswap 1 036 0234 ram 0 2 9 1 -1 0 0 0 0 * * The file /usr/sys/conf/xenixconf will have to have the following * entries in it. * * * disk 1 * console 1 * acu 1 * printer 1 * screen 1 * ramswap 1 (Add this) * *** note that the minor number 0377 causes the kernel to autoconfigure * root disk 0377 * pipe disk 0377 * * Max Number blocks of swap * swap ramswap 5 0 32765 * *** Note that the number 5 is the minor number of the device and 0 is the * base address where the swapper starts and 4096 is the number of blocks * available to the swapper. Change this number to reflect the ramswap * device, you want, based on the amount of memory and the address of where * the swap starts. If you have any swap space on a disk drive and you know * how many blocks of disk swap there are, then you will want to set the * maximum number of blocks as follows: * * ramswap + number of blocks available on the hard disk = Max # blocks * of swap * * The driver will then automatically overflow to the hard disk swapper * when the ramswap becomes full. The default overflow to the hard disk * is set to the swap partition of the primary hard disk (34). * * STEP 5 (Optional) >-------------------------------------------------------- * * If you have a secondary hard drive that you want the swapper to overflow * on then you will need to use adb to set the device number you wish, as * follows: * * The following devices are available to be used as disk swappers. * Get the minor number for the appropriate device from the list: * * Minor # * vv * brw-r----- 1 sys 1, 40 Mar 18 12:12 /dev/hd1 * brw-r----- 1 sys 1, 48 Mar 18 12:12 /dev/hd2 * brw-r----- 1 sys 1, 56 Mar 18 12:12 /dev/hd3 * ***NOTE: The minor number 34 is used for the swapper on drive 0. * * Enter the following commands: * * adb -w /xenix * swapmin?w xx (where xx is the minor number of the disk you want) * swapmin?d (this displays the number you have entered) * * (Type CNTRL-D to exit and then re-boot the system) * ***NOTE: If you do not re-boot the system then the overflow disk swapper will * not be opened and any subsequent attempts to read/write to the disk * device will fail. * * The overflow swapper is now set. * * STEP 6 (Optional) >-------------------------------------------------------- * * You can also use the ram swap as a mounted file system. The device * driver will support this. The only thing that you must be aware of * is that if you use 1 ram partition as swap and the other as a file * then you must use mkfs to make the file system on the device and * use the exact size of the device as a parameter to mkfs. DO NOT * attempt to make a file system on the device that is larger than * the device. If you do this then you may have trouble when the * swapper overflows and writes on the file system that overflowed * to the hard disk. */ #include "../h/param.h" #include "../h/inode.h" #include "../h/buf.h" #include "../h/conf.h" #include "../h/dir.h" #include "../h/user.h" dev_t swapmaj = 1; /* The major # of the overflow disk partition */ dev_t swapmin = 34; /* The minor # of the overflow disk partition */ short firsttime = 1; /* The flag for displaying the ram swap message. */ struct buf ramtab; struct buf rambuf; struct s_pdev { caddr_t base; daddr_t size; }; /* The struct allows many different combinations of ramswap. The limit is 5 Meg of memory, so if the base address is 3 Meg then only a maximum of 2 Meg of swap is allowed. The device names describe the amount of ram available for the swapper and the base address to start the ram swapper at. Like so: ra11 = 1 Meg swap + 1 Meg base ra12 = 1 Meg swap + 2 Meg base ra21 = 2 Meg swap + 1 Meg base NOTE: The two numbers added together equal the amount of addressable ram in the system. */ struct s_pdev pdev[] = { (caddr_t)0x100000, 0x100000L, /* 0 ra11 */ (caddr_t)0x200000, 0x100000L, /* 1 ra12 */ (caddr_t)0x300000, 0x100000L, /* 2 ra13 */ (caddr_t)0x400000, 0x100000L, /* 3 ra14 */ (caddr_t)0x100000, 0x200000L, /* 4 ra21 */ (caddr_t)0x200000, 0x200000L, /* 5 ra22 */ (caddr_t)0x300000, 0x200000L, /* 6 ra23 */ (caddr_t)0x100000, 0x300000L, /* 7 ra31 */ (caddr_t)0x200000, 0x300000L, /* 8 ra32 */ (caddr_t)0x100000, 0x400000L, /* 9 ra41 */ NULL, NULL }; #define NMINORS ((sizeof (pdev) / sizeof (struct s_pdev)) - 1) #ifdef V7 # define paddr(bp) ((bp)->b_un.b_addr) #endif /*V7*/ ramopen(dev, flag, class) dev_t dev; int flag, class; { if (firsttime) { firsttime = 0; if (class) { #ifdef V7 printf("Ram Swap area %d blocks\n", pdev[minor(dev)].size / BSIZE); #else /*V7*/ printf("Ram Swap area %dk\n", pdev[minor(dev)].size / 1024); #endif /*V7*/ } } if (minor(dev) >= NMINORS) u.u_error = ENXIO; /* If the dkopen() blows off, u.u_error is already set up */ dkopen(swapmin, flag, class); } ramclose(dev, flag, class) dev_t dev; int flag, class; { dev = makedev(swapmaj, swapmin); #if !defined(V7) && !defined(V31) /* 3.2 and later kernels have dev_open() available */ if (!dev_open(dev, class? IFBLK : IFCHR)) #endif /*!V7 && !V31*/ dkclose(dev, flag, class); } ramstrat(bp) struct buf *bp; { register caddr_t rp; register caddr_t wp; register daddr_t cnt; register daddr_t dcnt; register daddr_t rcnt; register daddr_t ends; #ifdef DEBUG printf("%s blk %d, cnt %d", (bp->b_flags&B_READ)? "Rd":"Wr", bp->b_blkno, bp->b_bcount); #endif /*DEBUG*/ cnt = bp->b_bcount; rp = (char *) (bp->b_blkno * BSIZE); ends = pdev[minor(bp->b_dev)].size; if ((daddr_t) rp >= ends) { /* If request begins after ram */ rcnt = 0; dcnt = cnt; bp->b_blkno -= ends/BSIZE; } else { if ((daddr_t) rp + cnt > ends) { /* If request ends after ram */ rcnt = ends - (daddr_t) rp; dcnt = cnt - rcnt; bp->b_blkno = 0; /* set disk xfer to block 0 */ } else { /* request completely in ram */ rcnt = cnt; dcnt = 0; } #ifdef DEBUG printf(" Mem, device = %d\n", bp->b_dev); #endif /*DEBUG*/ rp += (daddr_t)pdev[minor(bp->b_dev)].base; if (bp->b_flags & B_READ) wp = (caddr_t)paddr(bp); else { wp = rp; rp = (caddr_t)paddr(bp); } if (dcnt) paddr(bp) += rcnt; #ifndef SLOW /* Lightning fast assembly copy routine */ copybuf(rp, wp, rcnt); #else /*SLOW*/ { register long *longw = (long *)wp; register long *longr = (long *)rp; register long longc = rcnt >> 2; while (longc--) *longw++ = *longr++; } rcnt &= 0x03; while (rcnt--) *wp++ = *rp++; #endif /*SLOW*/ } if (dcnt) { bp->b_bcount = dcnt; bp->b_dev = makedev(swapmaj, swapmin); #ifdef DEBUG printf(" Dk, device = %d\n", bp->b_dev); #endif /*DEBUG*/ dkstrat(bp); /* iodone will be called by dkuintr() */ return; } bp->b_resid = 0; /* set to zero in case the hard disk */ /* sets the error flag during the */ /* transfer. We should never have a */ /* failure on a transfer, unless some */ /* thing is very wrong */ iodone(bp); } /* The following two are for /dev/rraxx access. Block device accesses do not use the read/write routines. Only the associated character devices use the read/write routines. */ ramread(dev) dev_t dev; { physio(ramstrat, &rambuf, dev, B_READ); } ramwrite(dev) dev_t dev; { physio(ramstrat, &rambuf, dev, B_WRITE); }