/********************************************************************** * Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. * * All Rights Reserved. * * Reference "/usr/src/COPYRIGHT" for applicable restrictions. * **********************************************************************/ static char Sccsid[] = "@(#)newfs.c 3.1 3/26/87"; /* #define CMDLINE /* for non-interactive usage - obsolete! */ /* #define DEBUG /* for partition table debugging printout */ /* * * File name: * * newfs.c * * Source file description: * * Friendly front end to /etc/mkfs (newfs). * * This program allows a user to make a file system by specifying the * generic disk name and partition number. Newfs determines the size * of the file system by reading the disk sizes table from the kernel. * Newfs forks a copy of mkfs to actually make the file system. * * This programs helps eliminate some of the confusion associated with * making file systems, i.e., is the size in 512 byte or 1K byte blocks? * Also, user does not need to look up the partition size. Assures * correct file system size even if non standard sizes used (dksizes.c). * * CAUTION!, this program depends on /usr/include/sys/devmaj.h. If the * order of major device numbers changes, newfs must be recompiled. * * Functions: * * main() The planes in spain fall MAINLY in the rain! * * OTHERS? * * Usage: * * Interactive usage: * * /etc/newfs (program prompts for disk name, etc.) * * Non-interactive usage: (obsolete) * * /etc/newfs [-t] disk [-c #] unit [dp] [fsname volname] * * -t print list of configured disk controllers/drives * disk generic disk name (rp06, rm03, rd52, rx50, etc.) * -c # # = RH11/RH70 MASSBUS controller number (default = 0) * unit physical disk unit number * dp disk partition number * fsname superblock file system name, fsname[6] * volname superblock volume label, volname[6] * * Compile: * * cd /usr/src/cmd; make newfs * * Modification History: * * 31 August 1985 * File created -- Fred Canter * */ #include <stdio.h> #include <a.out.h> #include <signal.h> #include <setjmp.h> #include <sys/param.h> #include <sys/devmaj.h> #include <sys/conf.h> #include <sys/ra_info.h> #include <sys/hp_info.h> #include <sys/types.h> #include <sys/stat.h> /* * Help messages */ char *help[] = { "The /etc/newfs (new file system) program allows you to make a new", "file system on a disk without knowing its size. A disk can be a", "physical disk unit or a logical sub-unit (partition), depending", "on the type of disk. Refer to Chapter 1 and Appendix D in the", "ULTRIX-11 System Management Guide for more information about disk", "partitioning.", "", "To execute a command, type the first letter of the command, then", "press <RETURN>. The command will execute, then return to the command", "prompt. The newfs command prompts you for the disk name and other", "information. If you need help answering the prompts, type a '?'.", "", "The newfs commands are:", "", "CTRL/C Abort current command and return to the command prompt.", "help Print this help message (? also prints help message).", "exit Exit from the newfs program.", "table Prints list of configured controllers and drives.", "newfs Make a new file system on a disk (or partition).", "", 0 }; char *h_dsknam[] = { "Enter the disk's generic name, using only lowercase characters.", "The generic name is the real name for the disk as opposed to its", "ULTRIX-11 mnemonic, for example, rp06 vs hp. Use the table command", "at the newfs prompt to list the names of all configured disks.", "", 0 }; char *h_cn[] = { "If the disk is a MASSBUS disk, enter the number of the RH11/RH70", "disk controller it is connected to. You can use the table command", "at the newfs prompt to list the MASSBUS controller numbers.", "", "The MASSBUS disks are:", " RH11/RH70 - RP04/5/6, RM02/3/5, and ML11", "", "The controller number is determined by the order in which the", "controllers were specified during the system generation, that is,", "controller zero was entered first, controller one second and", "controller two third, etc.", "", 0 }; char *h_unit[] = { "Enter the unit number of the disk on which the new file system is", "to be created. You can use the table command at the newfs prompt", "to list all available disk units.", "", 0 }; char *h_density[] = { "Enter the density of the RX02 floppy disk. Normally, this is", "double density. Single density is used for compatibility with", "RX01 floppys. The density you specify must match the density you", "specified when you initially formatted the disk. If the disk has", "not yet been formatted, you must go back and format the disk using", "the /etc/rx2fmt command before you can create a filesystem on it.", "", 0 }; char *h_fsn[] = { "The file system name is used to fill in the fsname[6] field in the", "superblock (see filsys(5)). The fsname has a maximum length of six", "characters. The fsname is usually the directory on which the file", "system will be mounted, for example, user1, or /tmp.", "", "The fsname is not required. If you respond with only a <RETURN>,", "the fsname field will remain uninitialized. The labelit(8) command", "can also be used to modify the superblock fsname[6] field.", "", 0 }; char *h_voln[] = { "The volume label is used to fill in the volname[6] field in the", "superblock (see filsys(5)). The volname has a maximum length of", "six characters. The volname should match the disk pack label. For", "example: ud_hp0, pack1, system, etc.", "", "The volname is not required. If you respond with only a <RETURN>,", "the volname field will remain uninitialized. The labelit(8) command", "can also be used to modify the superblock volname[6] field.", "", 0 }; char *h_dpart[] = { "Enter the number of the disk partition where the file system is to", "be created. There are eight possible partitions, numbered 0 thru 7.", "Not all disks use all of the eight possible disk partitions. Refer", "to Appendix D in the ULTRIX-11 System Management Guide for a disk", "partition layout of all supported disks.", "", 0 }; #ifdef CMDLINE /* non-interactive mode - obsolete! */ char *oldusage[] = { "", "Usage:\t/etc/newfs [-t] disk [-c #] unit [dp] [fsname volname]", "Interactive usage:\t/etc/newfs\t(prompts for disk name, etc.)", "", " -t print list of configured disk controllers/drives", " disk generic disk name (rp06, rm03, rd52, rx50, etc.)", " -c # # = RH11/RH70 disk controller number (default = 0)", " unit physical disk unit number", " dp disk partition number (0 -> 7)", " fsname superblock file system name, fsname[6]", " volname superblock volume label, volname[6]", "", 0 }; #endif CMDLINE char *usage[] = { "usage: /etc/newfs", "", }; char *bcnerr = "Invalid MASSBUS cntlr number with -c option!\n"; char *bunerr = "Invalid unit number!\n"; /* * Namelist values read from the kernel. */ struct nlist nl[] = { { "_cputype" }, #define X_CPUTYPE 0 { "_nrk" }, #define X_NRK 1 { "_rk_dt" }, #define X_RK_DT 2 { "_nrp" }, #define X_NRP 3 { "_rp_dt" }, #define X_RP_DT 4 { "_nuda" }, #define X_NUDA 5 { "_nra" }, #define X_NRA 6 { "_ra_inde" }, #define X_RA_INDEX 7 { "_ra_ctid" }, #define X_RA_CTID 8 { "_ra_drv" }, #define X_RA_DRV 9 { "_nrl" }, #define X_NRL 10 { "_rl_dt" }, #define X_RL_DT 11 { "_nhp" }, #define X_NHP 12 { "_hp_inde" }, #define X_HP_INDEX 13 { "_hp_dt" }, #define X_HP_DT 14 { "_nhk" }, #define X_NHK 15 { "_hk_dt" }, #define X_HK_DT 16 { "_ra_mas" }, #define X_RA_MAS 17 { "_ud_size" }, #define X_UD_SIZES 18 { "_rq_size" }, #define X_RQ_SIZES 19 { "_rc_size" }, #define X_RC_SIZES 20 { "_hp_size" }, #define X_HP_SIZES 21 { "_hk_size" }, #define X_HK_SIZES 22 { "_rp_size" }, #define X_RP_SIZES 23 { "_bdevsw" }, #define X_BDEVSW 24 { "_nhx" }, #define X_NHX 25 { "_rootdev" }, #define X_ROOTDEV 26 { "" }, }; /* * Disk partition sizes table. */ struct pt_info { daddr_t pt_sb; /* starting block number (1KB logical block) */ daddr_t pt_nb; /* length in 1KB logical blocks */ } pt_info[8]; /* * Disk controller and drive info table. * Loaded with controller type and type of each * configured disk. Used for making the fstab, * special files, and file systems. */ #define DI_MSCP 01 /* MSCP controller flag */ #define DI_MASS 02 /* MASSBUS controller flag */ #define DI_NPD 04 /* Non-partitioned disk flag */ #define DI_HX 010 /* RX02 special case flag */ #define DI_RX50 020 /* RX50/RX30 special case flag */ #define DI_FIRST 040 /* defines first MSCP controller so RX50/KLESI offline message once, instead of 4 messages for each unit */ int rk_gdti(), rp_gdti(), ra_gdti(), rl_gdti(); int hx_gdti(), hp_gdti(), hk_gdti(); struct di_info { char *di_typ; /* Controller type (name string) */ char *di_name; /* Two char ULTRIX-11 mnemonic */ /* ("ra" changed on the fly to ra|rc|rd|rx) */ char di_cn; /* Controller number (if massbus or mscp) */ char di_nunit; /* Number units (0 if cntlr not configured) */ char di_bmaj; /* Block major device number */ char di_rmaj; /* Raw major device number */ int (*di_func)(); /* Call this function to get drive type info */ int di_flags; /* Flags (massbus, mscp, NP disk, etc.) */ int di_dt[8]; /* Each unit's type (index into dt_info[]) */ /* Zero indicates non existent drive */ } di_info[] = { { "RK11", "rk", 0, 0, RK_BMAJ, RK_RMAJ, rk_gdti, DI_NPD }, { "RP11", "rp", 0, 0, RP_BMAJ, RP_RMAJ, rp_gdti, 0 }, { "MSCP", "ra", 0, 0, RA_BMAJ, RA_RMAJ, ra_gdti, (DI_MSCP|DI_FIRST) }, { "MSCP", "ra", 1, 0, RA_BMAJ, RA_RMAJ, ra_gdti, DI_MSCP }, { "MSCP", "ra", 2, 0, RA_BMAJ, RA_RMAJ, ra_gdti, DI_MSCP }, { "MSCP", "ra", 3, 0, RA_BMAJ, RA_RMAJ, ra_gdti, DI_MSCP }, { "RL11", "rl", 0, 0, RL_BMAJ, RL_RMAJ, rl_gdti, 0 }, { "RX11", "hx", 0, 0, HX_BMAJ, HX_RMAJ, hx_gdti, DI_HX }, { "MASSBUS", "hp", 0, 0, HP_BMAJ, HP_RMAJ, hp_gdti, DI_MASS }, { "MASSBUS", "hm", 1, 0, HM_BMAJ, HM_RMAJ, hp_gdti, DI_MASS }, { "MASSBUS", "hj", 2, 0, HJ_BMAJ, HJ_RMAJ, hp_gdti, DI_MASS }, { "RK611", "hk", 0, 0, HK_BMAJ, HK_RMAJ, hk_gdti, 0 }, { 0 }, }; /* * System's disk type info structure. * * Disk drive type ID definitions (must be unique): */ /* ra_info: RX33 RX50 RD31 RD32 RD51 RD52 RD53 RD54 RC25 RA60 RA80 RA81 */ /* hp_info: RP04 RP05 RP06 RM02 RM03 RM05 ML11 */ #define RK05 5 #define RX02 1 #define RL01 10240 #define RL02 20480 #define RK06 0 #define RK07 02000 #define RP02 2 #define RP03 3 struct dt_info { char *dt_lname; /* disk type name in lowercase */ char *dt_uname; /* disk type name in uppercase */ int dt_type; /* numeric disk type */ char dt_pmask; /* BIT WISE -- disk partition usage mask */ char dt_smask; /* BIT WISE -- system disk unwritable */ /* partitions. If zero, can't be system disk */ int dt_flags; /* flags is flags */ } dt_info[] = { /* DUMMY ENTRY: must be here, see di_info.di_dt[] */ "", "", -1, 0, 0, 0, "rx02", "RX02", RX02, 0, 0, DI_NPD, "rk05", "RK05", RK05, 0, 0, DI_NPD, "ml11", "ML11", ML11, 0, 0, DI_MASS, "rx33", "RX33", RX33, 0200, 0, DI_RX50, /* using DI_RX50 for RX33 */ "rx50", "RX50", RX50, 0200, 0, DI_RX50, "rd31", "RD31", RD31, 0341, 0341, 0, "rd32", "RD32", RD32, 0217, 0207, 0, "rd51", "RD51", RD51, 0221, 0221, 0, "rd52", "RD52", RD52, 0217, 0207, 0, "rd53", "RD53", RD53, 0217, 0207, 0, "rd54", "RD54", RD54, 0217, 0207, 0, "rl01", "RL01", RL01, 0201, 0201, 0, "rl02", "RL02", RL02, 0203, 0203, 0, "rk06", "RK06", RK06, 0107, 0107, 0, "rk07", "RK07", RK07, 0213, 0213, 0, "rp02", "RP02", RP02, 0107, 0107, 0, "rp03", "RP03", RP03, 0213, 0213, 0, "rp04", "RP04", RP04, 0117, 0107, DI_MASS, "rp05", "RP05", RP05, 0117, 0107, DI_MASS, "rp06", "RP06", RP06, 0377, 0307, DI_MASS, "rm02", "RM02", RM02, 0217, 0207, DI_MASS, "rm03", "RM03", RM03, 0217, 0207, DI_MASS, "rm05", "RM05", RM05, 0377, 0207, DI_MASS, "ra60", "RA60", RA60, 0277, 0207, 0, "ra80", "RA80", RA80, 0217, 0207, 0, "ra81", "RA81", RA81, 0377, 0207, 0, "rc25", "RC25", RC25, 0237, 0207, 0, 0 }; /* * Number of 512 byte blocks per cylinder * for each type of disk. */ #define RP23_BPC 200 /* RP02/3 */ #define RP456_BPC 418 /* RP04/5/6 */ #define RM23_BPC 160 /* RM02/3 */ #define RM5_BPC 608 /* RM05 */ #define RK67_BPC 66 /* RK06/7 */ /* * Misc. stuff for setup of user file systems. */ int cputype; /* current processor type */ int rootdev; /* block major/minor of root device */ char *dsk_sfn = "/dev/newfs.dsf"; char *lpfdir = "lost+found"; char fsname[20]; /* superblock fsname (also mounted on directory name) */ char volname[20]; /* superblock volname */ char rdisk[20]; /* raw special file name (/dev/r??##) */ char syscmd[100]; /* system command buffer */ char rbuf[512]; /* general read buffer */ /* * Kernel data structures needed to determine * disk controller and drive configuration. */ struct dksize { daddr_t nblocks; /* partition length - 512 byte blocks (sectors) */ int cyloff; /* partition starting cylinder number */ }; struct bdevsw bdevswb; /* * RK05 * NED = -1 * RK05 = 1 */ int nrk; char rk_dt[8]; int rk_size = 4872; /* * RP02/3 * NED = -1 * RP02 = 0 * RP03 = 1 * Note: must read each configured RP02/3 unit to * force update of rp_dt[]. */ int nrp; char rp_dt[8]; struct dksize rp_sizes[8]; /* * MSCP (UDA50 RC25 RQDX RUX50) * NED = 0 * See /usr/include/sys/ra_info.h for drive types. * * Note: MSCP drive type info arrays are non-symetrical * ra_index must be used to access drive type info. */ int nuda; /* Number of configured MSCP controllers */ char nra[MAXUDA]; /* Number of units configured on each controller */ char ra_ctid[MAXUDA];/* Controller type ID and micro-code rev level */ char ra_index[MAXUDA];/* Index into drive type info ra_drv[] */ struct ra_drv ra_drv[MAXUDA*8]; /* RA drive info (see ra_info.h) */ daddr_t ra_mas[MAXUDA]; /* Size of maintenance area */ struct rasize ud_sizes[8]; /* UDA50 partition sizes */ struct rasize rc_sizes[8]; /* RC25 partition sizes */ struct rasize rq_sizes[8]; /* RQDX partition sizes */ /* * RL01/2 * NED = -1 * RL01 = 10240 * RL02 = 20480 */ int nrl; int rl_dt[4]; /* SIZE: drive type = size (RL01=10240, RL02=20480) */ /* * RX02 */ int nhx; /* * MASSBUS (HP HM HJ) * NED = 0 * See /usr/include/sys/hp_info.h for drive types. * * Note: MASSBUS drive type info arrays are non-semetrical * hp_index must be used to access drive type info. */ char hp_index[MAXRH]; /* Index into drive type info arrays */ char nhp[MAXRH]; /* Number units per cntlr (0 = not config) */ char hp_dt[MAXRH*8]; /* Drive type of each drive */ struct dksize hp_sizes[32]; /* disk partition sizes */ /* * RK06/7 * NED = -1 * RK06 = 0 * RK07 = 02000 */ int nhk; int hk_dt[8]; struct dksize hk_sizes[8]; #define MKFS 1 #define BLOCK 0 #define RAW 1 #define HELP 2 #define NOHELP 0 #define YES 1 #define NO 0 #define LBSIZE 50 char lbuf[LBSIZE]; char *mntdir="/Newfs_mntdir1"; /* dir to mount for lost+found work */ int imode; /* Interactive mode */ int cntlr; /* MASSBUS controller number */ int unit; /* Disk unit number */ int dpart; /* Disk partition number */ int hx_single; /* == 1 single density RX02 (RX01 mode) */ jmp_buf savej; int sumask; main(argc, argv) int argc; char *argv[]; { int intr(); register struct dt_info *dtp; register struct di_info *dip; register int i; int mem; long soff; #ifdef CMDLINE int part, gotunit, gotdisk, gotfsname; /* for non-interactive use */ #endif CMDLINE if(sucheck()) exit(1); /* * Get CPU type and other info from kernel. */ if(nlist("/unix", nl) < 0) { printf("\nCan't access namelist in /unix!\n"); exit(1); } if(nl[X_CPUTYPE].n_value == 0) { printf("\nCan't get needed symbol values from /unix namelist!\n"); exit(1); } if((mem = open("/dev/mem", 0)) < 0) { printf("\nCan't open /dev/mem (memory) for reading!\n"); exit(1); } if(nl[X_ROOTDEV].n_value == 0) { printf("\nCan't get root device from kernel!\n"); exit(1); } else { lseek(mem, (long)nl[X_ROOTDEV].n_value, 0); read(mem, (char *)&rootdev, sizeof(rootdev)); } if (nl[X_CPUTYPE].n_value) { lseek(mem, (long)nl[X_CPUTYPE].n_value, 0); read(mem, (char *)&cputype, sizeof(cputype)); } else { printf("Cannot get CPU type from kernel!\n"); cputype=0; } while(1) { i = 0; switch(cputype) { case 23: case 24: case 34: case 40: case 44: case 45: case 53: case 55: case 60: case 70: case 73: case 83: case 84: break; default: i++; break; } if(i == 0) break; printf("\n%d is not a supported CPU type!\n", cputype); printf("\nPlease enter the CPU type with features most closely"); printf("\nmatching your CPU, choose one of the following CPUs:\n"); printf("\n 23 24 34 40 44 45 55 60 70 73 83 84\n"); if(getline(NOHELP) < 0) continue; cputype = atoi(lbuf); continue; } /* * Find out what disk controllers/drives are present * and save the necessary info in the di_info[] table. * * 1. Read bdevsw[] entry for disk controller. * 2. If d_tab entry is 0, controller not configured. * 3. Make a special file to access cntlr unit 0. * 4. Open unit 0 to force driver to load ??_dt[] with drive types. * Note: RP require reading each unit. * 5. Call appropriate routine to get drive type info and * load it into di_info[]. * */ for(dip=di_info; dip->di_typ; dip++) { /* 1 */ soff = (long)nl[X_BDEVSW].n_value + (long)(sizeof(struct bdevsw) * dip->di_bmaj); lseek(mem, (long)soff, 0); read(mem, (char *)&bdevswb, sizeof(struct bdevsw)); /* 2 */ dip->di_nunit = 0; if(bdevswb.d_tab == 0) continue; /* 3 */ unlink(dsk_sfn); if(mknod(dsk_sfn, 020400, (dip->di_rmaj<<8) | (dip->di_cn<<6)) < 0) { printf("\nERROR: mknod for %s controller %d failed!\n", dip->di_typ, dip->di_cn); exit(1); } /* 4 */ if((i = open(dsk_sfn, 0)) >= 0) close(i); unlink(dsk_sfn); /* 5 */ for(i=0; i<8; i++) /* set all drive types to NED */ dip->di_dt[i] = 0; (*dip->di_func)(MKFS, dip, mem); /* get drive type info */ } sumask = umask(0); imode = 0; if(argc == 1) { /* Interactive mode */ imode++; printf("\nULTRIX-11 New File System Program\n"); printf("\nFor help, type ? or help, then press <RETURN>."); setjmp(savej); signal(SIGINT, intr); printf("\n"); while(1) { printf("\nCommand < exit help newfs table >: "); if(getline(NOHELP) <= 0) continue; /* user typed help, <RETURN> or <CTRL/D> */ switch(lbuf[0]) { case 'h': case '?': /* print help message */ pmsg(help); continue; case 'e': /* exit from program */ umask(sumask); exit(0); case 't': /* print device table */ dotable(); continue; case 'n': /* make a new file system */ dtp = getinfo(); donewfs(dtp, mem); continue; default: printf("\n%s - not a valid command!\n", lbuf); continue; } } } #ifdef CMDLINE /* * Non interactive mode. */ signal(SIGINT, intr); unit = 0; part = gotunit = gotdisk = gotfsname = 0; cntlr = 0; for(i=1; argv[i]; i++) { if(equal("-t", argv[i])) { /* TABLE */ dotable(); if(argc == 2) xit(); else { argc--; continue; } } if(equal("-c", argv[i])) { /* CONTROLLER NUMBER */ /* * For now, cntlr limit is 3. * Check again later, when we know device type. */ i++; /* get next arg */ if((strlen(argv[i]) != 1) || (argv[i][0] < '0') || (argv[i][0] > '3')) { printf("\nnewfs: %s", bcnerr); pmsg(oldusage); errxit(); } cntlr = atoi(argv[i]); continue; } if ((strlen(argv[i]) == 1) && ((argv[i][0] >= '0') && (argv[i][0] <= '7'))) { /* unit # */ if (gotunit == 0) { unit = atoi(argv[i]); gotunit++; if((unit < 0) || (unit > 7)) { printf("\nnewfs: %s", bunerr); pmsg(oldusage); errxit(); } } else { /* already have unit, must be dp# */ part = atoi(argv[i]); if((unit < 0) || (unit > 7)) { printf("\nnewfs: %s", bunerr); pmsg(oldusage); errxit(); } } continue; } else { /* must assume it's a device name */ if (gotdisk == 0) { for(dtp=dt_info; dtp->dt_lname; dtp++) if(equal(argv[i], dtp->dt_lname)) { gotdisk++; break; } if(dtp->dt_lname == 0) { printf("\nnewfs: %s - invalid device name!\n", argv[i]); pmsg(oldusage); errxit(); } } else { /* look for optional fsname/volname */ if (gotfsname == 0) { gotfsname++; strncpy(fsname, argv[i], 6); } else { /* have fsname, must be volname */ strncpy(volname, argv[i], 6); i--; /* should be end of input */ if (argv[i]) { printf("newfs: too many args.\n"); pmsg(oldusage); errxit(); } break; } } } if(((strlen(argv[i]) == 1)) && ((argv[i][0] >= '0') && (argv[i][0] <= '7'))) { /* partition# */ unit = atoi(argv[i]); if((unit < 0) || (unit > 7)) { printf("\nnewfs: %s", bunerr); pmsg(oldusage); errxit(); } continue; } } /* for i in argv[i] DONE scanning input */ donewfs(dtp, mem); xit(); #endif CMDLINE } /* * Ask user for device name, * [cn], unit number, [tty##]. */ getinfo() { register struct dt_info *dp; register int cc; while(1) { do printf("\nDisk name (? for help) < rd52, rp06, ra60, etc. >: "); while((cc = getline(h_dsknam)) < 0); if(cc == 0) continue; /* user typed <RETURN> */ for(dp=dt_info; dp->dt_lname; dp++) if(strcmp(lbuf, dp->dt_lname) == 0) break; if(dp->dt_lname == 0) { printf("\n%s - bad disk name!\n", lbuf); continue; } break; } while(1) { cntlr = 0; if(!(dp->dt_flags&DI_MASS)) /* only prompt if MASSBUS */ break; do printf("\nMASSBUS disk controller number < 0 1 2 >: "); while((cc = getline(h_cn)) < 0); if(cc == 0) continue; /* <RETURN> */ if((cc != 1) || (lbuf[0] < '0') || (lbuf[0] > '2')) { printf("\n%s - bad controller number!\n", lbuf); continue; } cntlr = lbuf[0] - '0'; break; } while(1) { unit = 0; do { if (dp->dt_type==RX02) printf("\nUnit number < 0 1 >: "); else printf("\nUnit number < 0 -> 7 >: "); } while((cc = getline(h_unit)) < 0); if(cc == 0) continue; if (dp->dt_type==RX02) /* RX02 can only be unit 0 or 1 */ if((cc == 1) && ((lbuf[0] == '0') || (lbuf[0] == '1'))) { unit = lbuf[0] - '0'; /* OK */ break; } else cc = 2;/* so catch it next line */ if((cc != 1) || (lbuf[0] < '0') || (lbuf[0] > '7')) { printf("\n%s - bad unit number!\n", lbuf); continue; } unit = lbuf[0] - '0'; break; } if ((dp->dt_flags&DI_NPD) && (dp->dt_type==RX02)) { hx_single = 0; /* set double density default */ while(1) { do { printf("\nsingle or double density? < double >: "); } while((cc = getline(h_density)) < 0); if(cc == 0) break; /* assume default (double density) */ if((lbuf[0] == 's') || (lbuf[0] == 'S')) { hx_single = 1; /* single density */ } break; } } while(1) { dpart = 0; /* Use parition 0 for RK05 */ if((dp->dt_flags&DI_NPD) && (dp->dt_type == RK05)) { dpart = 0; break; } /* Use parition 7 if RX02 (DI_NPD) or if RX50/RX33 (DI_RX50) */ if((dp->dt_flags&DI_NPD) || (dp->dt_flags&DI_RX50)) { dpart = 7; break; } if(dp->dt_type == ML11) { /* ML11 uses unit number instead */ dpart = unit; break; } while(1) { do printf("\nDisk partition number < 0 -> 7 >: "); while((cc = getline(h_dpart)) < 0); if(cc == 0) continue; if((cc != 1) || (lbuf[0] < '0') || (lbuf[0] > '7')) { printf("\n%s - bad partition number!\n", lbuf); continue; } dpart = lbuf[0] - '0'; /* check if disk can utilize this partition or not */ if((dp->dt_pmask&(1 << dpart)) == 0) { printf("\nSorry, %s disk does not use partition %d!\n", dp->dt_uname, dpart); continue; } break; } break; } while(1) { do printf("\nSuperblock: file system name (fsname) < ? for help >: "); while((cc = getline(h_fsn)) < 0); if(cc == 0) { sprintf(&fsname, " "); break; } if(cc > 6) { printf("\nfsname - 6 characters maximum!\n"); continue; } sprintf(&fsname, "%s", lbuf); break; } while(1) { do printf("\nSuperblock: volume name (volname) < ? for help >: "); while((cc = getline(h_voln)) < 0); if(cc == 0) { sprintf(&volname, " "); break; } if(cc > 6) { printf("\nvolname - 6 characters maximum!\n"); continue; } sprintf(&volname, "%s", lbuf); break; } return(dp); } /* * Print table of configured disk controllers * and drives on each controller. */ dotable() { register struct di_info *dip; register int j; printf("\nULTRIX-11 System's Disk Configuration:\n"); printf("\nX = disk not configured, "); printf("NED = disk configured but not present.\n"); printf("\nDisk Cntlr Unit Unit Unit Unit "); printf("Unit Unit Unit Unit"); printf("\nCntlr # 0 1 2 3 "); printf("4 5 6 7"); printf("\n----- ----- ---- ---- ---- ---- "); printf("---- ---- ---- ----"); for(dip=di_info; dip->di_typ; dip++) { if(dip->di_nunit == 0) continue; printf("\n%-6s %-5d ", dip->di_typ, dip->di_cn); for(j=0; j<8; j++) { if(j >= dip->di_nunit) printf("X "); else if(dip->di_dt[j] == 0) printf("NED "); else printf("%-4s", dt_info[dip->di_dt[j]].dt_uname); printf(" "); } } printf("\n"); } /* * need funct header */ donewfs(dp, mem) register struct dt_info *dp; int mem; { register struct di_info *dip; register int i, j; int found, problem; char buf[128]; /* buffer to hold mntdir + lpfdir + "junkxx" */ struct stat statb; found = 0; for(dip=di_info; dip->di_typ; dip++) { if(dip->di_nunit == 0) continue; /* cntlr not configured */ /* If controllers don't match then it's only the wrong one if * DI_MASS flag is set (since user specified which MASSBUS cntlr#). * The cntlr variable is sometimes 0 when it really could be * 1 or 2, so we check them all for the MSCP case. */ if(dip->di_cn != cntlr) if (dip->di_flags&DI_MASS) continue; /* wrong MASSBUS controller */ for(j=0; j < dip->di_nunit; j++) { if(j != unit) continue; /* wrong unit */ if(dp->dt_type == dt_info[dip->di_dt[j]].dt_type) { found++; break; } } if(found) break; } if(dip->di_typ == 0) { printf("\n%s Cntlr %d Unit %d -- ", dp->dt_uname, cntlr, unit); printf("not configured or not present!\n"); return; } /* * Don't allow the user to make file systems * on partitions used by the system, if this * is the system disk. * Notes: RL01 uses drives 0 & 1 for system. * System disk can only be on controller zero. */ if((dp->dt_type == RL01) && (unit == 1)) j = 0; /* root device will be unit 0 */ else j = unit; i = (dip->di_bmaj << 8) | (j << 3); if(i == (rootdev & ~7)) { /* this is the system disk */ if(dp->dt_smask & (1 << dpart)) { printf("\n\7\7\7NEWFS ABORTED: "); printf("would overwrite part of the system disk!\n"); return; } } /* * RX50/RX33 special case, * open drive and get sizes info again. * For RX33, media size can change any time because * RX33 works with both RX33 (1200 blocks) and RX50 (400 blocks). * Also, RA driver can't detect media change or off-line * until the floppy door is closed (with media mounted). */ while(1) { if((dp->dt_flags&DI_RX50) == 0) break; /* not RX50/RX33 disk */ j = open(dsfn(RAW, unit, dpart, dip), 0); if((j >= 0) && (read(j, (char *)&rbuf, 512) == 512)) { close(j); if (nl[X_RA_DRV].n_value) { j = 0; /* need to know how many MSCP units */ for(i=0; i<MAXUDA; i++) j += nra[i]; lseek(mem, (long)nl[X_RA_DRV].n_value, 0); read(mem, (char *)&ra_drv, sizeof(struct ra_drv) * j); } } else { if(j >= 0) close(j); printf("\n%s Unit %d appears to be off-line!\n", dp->dt_uname, unit); return; } break; } spt(unit, dip); /* set partition sizes table */ #ifdef DEBUG for (j=0; j<=7; j++) printf("%ld %ld\n",pt_info[j].pt_nb, pt_info[j].pt_sb); #endif DEBUG sprintf(syscmd, "/etc/mkfs %s %D %s %d %.6s %.6s", dsfn(RAW, unit, dpart, dip), (long)pt_info[dpart].pt_nb/2, dt_info[dip->di_dt[unit]].dt_lname, cputype, fsname, volname); printf("\nMake file system command will be:\n"); printf("\n %s\n", syscmd); printf("\nPress <RETURN> to continue (or <CTRL/C> to abort):"); while(getchar() != '\n'); printf("\n%s\n", syscmd); if (system(syscmd) != 0) { printf("\nERROR: make file system failed\n"); return(1); } problem=0; /* only a problem if > 8 */ while(1) { if (stat(mntdir, &statb) < 0) { if (mkdir(mntdir, 755) < 0) { printf("\nnewfs: cannot make directory %s!\n", mntdir); printf("Warning: no lost+found directory was created on the new filesystem.\n"); return(1); } else { /* OK */ chmod(mntdir, 0755); break; } } else if ((statb.st_mode&S_IFMT) == S_IFDIR) { mntdir[13] += 1; if (problem++ >= 8) { /* try ...dir1 through ...dir9 */ printf("\nnewfs: cannot create a unique mount directory!\n", mntdir); printf("Warning: no lost+found directory was created on the new filesystem.\n"); return(1); } } else { /* existing mntdir is not directory, zap it and continue */ sprintf(syscmd, "rm -f %s", mntdir); system(syscmd); /* continue */ } } /* while(1) */ /* * Mount the file system and chmod 0755. * Make the lost+found directory. */ sprintf(syscmd,"/etc/mount %s %s", dsfn(BLOCK, unit, dpart, dip), mntdir); if(system(syscmd) != 0) { printf("newfs: cannot mount %s on %s\n", dsfn(BLOCK, unit, dpart, dip), mntdir); printf("Warning: no lost+found directory was created on the new filesystem.\n"); /* rmdir and return */ } else { /* the mount succeeded, create some junk files */ strcpy(buf, mntdir); /* start at mount point */ strcat(buf, "/"); strcat(buf, lpfdir); /* tack on "/lost+found" */ while(1) { if ((mkdir(buf, 0700)) < 0) printf("Warning: cannot mkdir %s\n", buf); for(i=0; i<25; i++) { sprintf(&syscmd, "%s/junk%d", buf, i); j = creat(&syscmd, 0666); if(j < 0) continue; write(j, (char *)&syscmd, 512); close(j); } sync(); sync(); sprintf(&syscmd, "rm -f %s/junk*", buf); system(syscmd); break; } /* while */ sprintf(syscmd, "/etc/umount %s", dsfn(BLOCK, unit, dpart, dip)); if(system(syscmd) != 0) { printf("\nWARNING: (%s) file system dismount failed!\n", dsfn(BLOCK, unit, dpart, dip)); } } rmdir(mntdir); } /* * Get a line of text from the terminal, * replace the newline with a NULL. * Return the string length (not counting the NULL). * Use lbuf[] as the buffer and LBSIZE as limit. * If ? or help is typed, print the help message, if * one is available, apologize if not. Return -1 after help. */ char *badline = "\n\7\7\7Bad input line, please try again!\n"; getline(hlp) char *hlp; { register int cc, ovflow; ovflow = 0; fflush(stdout); while(1) { lbuf[0] = '\0'; if(fgets(&lbuf, LBSIZE, stdin) == NULL) { printf("%s", badline); return(-1); /* reprint message */ } for(cc=0; lbuf[cc]; cc++) ; if((cc == 0) || (lbuf[0] == '\n')) return(0); /* (cc==0) says user typed just a <RETURN> */ if(lbuf[cc-1] != '\n') { /* line too long */ ovflow++; continue; } if(ovflow) { printf("\nLine too long, please try again!\n"); return(-1); } cc--; lbuf[cc] = '\0'; if((lbuf[0] == '?') || equal("help", lbuf) || equal("h", lbuf)) { if(hlp) { pmsg(hlp); return(-1); } } return(cc); } } equal(a, b) char *a, *b; { return(!strcmp(a, b)); } pmsg(str) char **str; { register int i; for(i=0; str[i]; i++) printf("\n%s", str[i]); fflush(stdout); } sucheck() { if(getuid() == 0) return(0); else { printf("\nOnly super-user can make file systems!\n"); return(1); } } intr() { if(imode == 0) { /* non interactive mode */ umask(sumask); exit(0); } longjmp(savej, 1); } errxit() { umask(sumask); exit(1); } xit() { umask(sumask); exit(0); } /* * Routines to fish the disk drive type * info out of the running kernel (/dev/mem). * BAD DEPENDENCY: routines need to know how each * disk driver defines NED and drive types. * * usage - identifies section of code calling ??_gdti(), * ONLY USED BY ra_gdti(). * MSF, called by make special files code. * MKFS, called by setup user file systems code. * dip - pointer to entry in di_info[]. * mem - open file descriptor for /dev/mem. * * Note: * The data structures used by these routines * are located before main(), so code in main can * access them. */ /* * RK05 * NED = -1 * RK05 = 1 */ rk_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; if (nl[X_NRK].n_value) { lseek(mem, (long)nl[X_NRK].n_value, 0); read(mem, (char *)&nrk, sizeof(nrk)); } if (nl[X_RK_DT].n_value) { lseek(mem, (long)nl[X_RK_DT].n_value, 0); read(mem, (char *)&rk_dt, sizeof(rk_dt)); } dip->di_nunit = nrk; for(i=0; i<nrk; i++) { if(rk_dt[i] != 1) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) if(dt_info[j].dt_type == RK05) break; dip->di_dt[i] = j; /* save index into drive info table */ } } } /* * RP02/3 * NED = -1 * RP02 = 0 * RP03 = 1 * Note: must read each configured RP02/3 unit to * force update of rp_dt[]. */ rp_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; for(i=0; i<nrp; i++) { mknod(dsk_sfn, 020400, (dip->di_rmaj<<8) | (i<<3)); if((j = open(dsk_sfn, 0)) >= 0) { read(j, (char *)&rbuf, 512); close(j); } unlink(dsk_sfn); } if (nl[X_NRP].n_value) { lseek(mem, (long)nl[X_NRP].n_value, 0); read(mem, (char *)&nrp, sizeof(nrp)); } if (nl[X_RP_DT].n_value) { lseek(mem, (long)nl[X_RP_DT].n_value, 0); read(mem, (char *)&rp_dt, sizeof(rp_dt)); } if (nl[X_RP_SIZES].n_value) { lseek(mem, (long)nl[X_RP_SIZES].n_value, 0); read(mem, (char *)&rp_sizes, sizeof(rp_sizes)); } dip->di_nunit = nrp; for(i=0; i<nrp; i++) { if(rp_dt[i] < 0) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) /* setup uses (RP02=2, RP03=3, so we add 2) */ if(dt_info[j].dt_type == (rp_dt[i] + 2)) break; dip->di_dt[i] = j; /* save index into drive info table */ } } } /* * MSCP (UDA50 RC25 RQDX RUX50) * NED = 0 * See /usr/include/sys/ra_info.h for drive types. * * Note: (usage argument) * * If usage == MSF (called from make special files code), * just get drive type info. If usage == MKFS (called from * setup user file systems code), get drive type info and * force all possible drives on-line by attempting open. * This ensures the size info is correct. * * Note: MSCP drive type info arrays are non-semetrical * ra_index must be used to access drive type info. */ ra_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; int cn, ind; int raunits; /* * Read in the controller and drive type info. */ if (nl[X_NUDA].n_value) { lseek(mem, (long)nl[X_NUDA].n_value, 0); read(mem, (char *)&nuda, sizeof(nuda)); } if (nl[X_NRA].n_value) { lseek(mem, (long)nl[X_NRA].n_value, 0); read(mem, (char *)&nra, MAXUDA); } if (nl[X_UD_SIZES].n_value) { lseek(mem, (long)nl[X_UD_SIZES].n_value, 0); read(mem, (char *)&ud_sizes, sizeof(ud_sizes)); } if (nl[X_RQ_SIZES].n_value) { lseek(mem, (long)nl[X_RQ_SIZES].n_value, 0); read(mem, (char *)&rq_sizes, sizeof(rq_sizes)); } if (nl[X_RC_SIZES].n_value) { lseek(mem, (long)nl[X_RC_SIZES].n_value, 0); read(mem, (char *)&rc_sizes, sizeof(rc_sizes)); } if (nl[X_RA_MAS].n_value) { lseek(mem, (long)nl[X_RA_MAS].n_value, 0); read(mem, (char *)&ra_mas, sizeof(daddr_t)*nuda); } raunits = 0; for(i=0; i<MAXUDA; i++) raunits += nra[i]; if (nl[X_RA_INDEX].n_value) { lseek(mem, (long)nl[X_RA_INDEX].n_value, 0); read(mem, (char *)&ra_index, MAXUDA); } if (nl[X_RA_CTID].n_value) { lseek(mem, (long)nl[X_RA_CTID].n_value, 0); read(mem, (char *)&ra_ctid, MAXUDA); } /* * If called from make user file systems code, * make sure size and on-line information in ra_drv[] * is updated by attempting to open each configured drive. * Only do this once, to avoid multiple UNIT off-lines. */ if(dip->di_flags&DI_FIRST) { for(i=0; i<nuda; i++) for(j=0; j<nra[i]; j++) { ind = (dip->di_rmaj << 8) | (i << 6) | (j << 3) | 7; mknod(dsk_sfn, 020400, ind); if((ind = open(dsk_sfn, 0)) >= 0) close(ind); unlink(dsk_sfn); } } if (nl[X_RA_DRV].n_value) { lseek(mem, (long)nl[X_RA_DRV].n_value, 0); read(mem, (char *)&ra_drv, sizeof(struct ra_drv) * raunits); } cn = dip->di_cn; ind = ra_index[cn]; dip->di_nunit = nra[cn]; for(i=0; i<nra[cn]; i++) { if(ra_drv[ind+i].ra_dt == 0) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) if(dt_info[j].dt_type == ra_drv[ind+i].ra_dt) break; dip->di_dt[i] = j; /* save index into drive info table */ } } /* * Change the controller name from MSCP to * the real name (UDA50, RQDX, etc.). */ dip->di_typ = ra_gcti(ra_ctid[cn]); /* * Change the two character ULTRIX-11 mnemonic to * ra, rc, rd, rx according to the controller type. */ switch((ra_ctid[cn] >> 4) & 017) { case UDA50: case UDA50A: case KDA50: dip->di_name[1] = 'a'; /* RA60/RA80/RA81 */ break; case KLESI: dip->di_name[1] = 'c'; /* RC25 */ break; case RQDX1: case RQDX3: dip->di_name[1] = 'd'; /* RD51/RD52/RD53/RD54 */ break; /* RD31/RD32 */ case RUX1: dip->di_name[1] = 'x'; /* RUX50 */ break; default: dip->di_name[1] = 'a'; /* UNKNOWN (can't happen) */ break; } } /* * Return a pointer to the controller name string * according to the controller type ID. */ ra_gcti(ctid) { switch((ctid >> 4) & 017) { case UDA50: return("UDA50"); case KDA50: return("KDA50"); case KLESI: return("KLESI"); case UDA50A: return("UDA50A"); case RQDX1: return("RQDX"); case RQDX3: return("RQDX3"); case RUX1: return("RUX1"); default: return("UNKNOWN"); } } /* * RX02 * RX02 driver does not have drive type info. * Always 2 RX02 if HX configured. */ hx_gdti(usage, dip, mem) register struct di_info *dip; { register int i; if (nl[X_NHX].n_value) { lseek(mem, (long)nl[X_NHX].n_value, 0); read(mem, (char *)&nhx, sizeof(nhx)); } if (nhx) { dip->di_nunit = 2; for(i=0; dt_info[i].dt_lname; i++) if(dt_info[i].dt_type == RX02) break; dip->di_dt[0] = i; /* unit 0 = RX02 */ dip->di_dt[1] = i; /* unit 1 = RX02 */ } } /* * RL01/2 * NED = -1 * RL01 = 10240 * RL02 = 20480 */ rl_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; if (nl[X_NRL].n_value) { lseek(mem, (long)nl[X_NRL].n_value, 0); read(mem, (char *)&nrl, sizeof(nrl)); } if (nl[X_RL_DT].n_value) { lseek(mem, (long)nl[X_RL_DT].n_value, 0); read(mem, (char *)&rl_dt, sizeof(rl_dt)); } dip->di_nunit = nrl; for(i=0; i<nrl; i++) { if(rl_dt[i] < 0) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) if(dt_info[j].dt_type == rl_dt[i]) break; dip->di_dt[i] = j; /* save index into drive info table */ } } } /* * MASSBUS (HP HM HJ) * NED = 0 * See /usr/include/sys/hp_info.h for drive types. * * Note: MASSBUS drive type info arrays are non-semetrical * hp_index must be used to access drive type info. */ int hpload = NO; /* HP info already loaded */ hp_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; int cn, ind; int hpunits; /* * Read in the controller and drive type info. */ if(hpload == NO) { hpload = YES; if (nl[X_NHP].n_value) { lseek(mem, (long)nl[X_NHP].n_value, 0); read(mem, (char *)&nhp, MAXRH); } if (nl[X_HP_SIZES].n_value) { lseek(mem, (long)nl[X_HP_SIZES].n_value, 0); read(mem, (char *)&hp_sizes, sizeof(hp_sizes)); } hpunits = 0; for(i=0; i<MAXRH; i++) hpunits += nhp[i]; if (nl[X_HP_INDEX].n_value) { lseek(mem, (long)nl[X_HP_INDEX].n_value, 0); read(mem, (char *)&hp_index, MAXRH); } if (nl[X_HP_DT].n_value) { lseek(mem, (long)nl[X_HP_DT].n_value, 0); read(mem, (char *)&hp_dt, hpunits); } } cn = dip->di_cn; ind = hp_index[cn]; dip->di_nunit = nhp[cn]; for(i=0; i<nhp[cn]; i++) { if(hp_dt[ind+i] == 0) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) if(dt_info[j].dt_type == hp_dt[ind+i]) break; dip->di_dt[i] = j; /* save index into drive info table */ } } /* * Change the controller name from MASSBUS to * the real name (RH11 or RH70). */ if(cputype == 70) dip->di_typ = "RH70"; else dip->di_typ = "RH11"; } /* * RK06/7 * NED = -1 * RK06 = 0 * RK07 = 02000 */ hk_gdti(usage, dip, mem) register struct di_info *dip; { register int i, j; if (nl[X_NHK].n_value) { lseek(mem, (long)nl[X_NHK].n_value, 0); read(mem, (char *)&nhk, sizeof(nhk)); } if (nl[X_HK_DT].n_value) { lseek(mem, (long)nl[X_HK_DT].n_value, 0); read(mem, (char *)&hk_dt, sizeof(hk_dt)); } if (nl[X_HK_SIZES].n_value) { lseek(mem, (long)nl[X_HK_SIZES].n_value, 0); read(mem, (char *)&hk_sizes, sizeof(hk_sizes)); } dip->di_nunit = nhk; for(i=0; i<nhk; i++) { if(hk_dt[i] < 0) dip->di_dt[i] = 0; /* NED (configured but not found) */ else { for(j=0; dt_info[j].dt_lname; j++) if(dt_info[j].dt_type == hk_dt[i]) break; dip->di_dt[i] = j; /* save index into drive info table */ } } } /* * Set up the disk partition sizes table. * * unit disk unit number * dip drive info table pointer */ spt(unit, dip) register struct di_info *dip; int unit; { register struct dksize *dsp; register struct rasize *rsp; int i, nbpc; for(i=0; i<8; i++) { pt_info[i].pt_nb = 0L; pt_info[i].pt_sb = 0L; } switch(dip->di_bmaj) { case RK_BMAJ: pt_info[0].pt_sb = 0L; pt_info[0].pt_nb = (long)rk_size; return(0); case RP_BMAJ: nbpc = RP23_BPC; dsp = &rp_sizes; break; case RA_BMAJ: switch((ra_ctid[dip->di_cn] >> 4) & 017) { case UDA50: case UDA50A: case KDA50: rsp = &ud_sizes; break; case KLESI: rsp = &rc_sizes; break; case RQDX1: case RQDX3: case RUX1: rsp = &rq_sizes; break; default: /* THIS CAN'T HAPPEN */ printf("\n(spt) - unknown controller type!\n"); return(1); } /* * RA sizes tables use following magic numbers: * (ud_sizes, rc_sizes, rq_sizes) * -1, partition ends at end of disk. * -2, partition ends at start of maintenance area. * Note: for the purposes of mkfs -1 and -2 mean the same. * This prevents a file system on partition 7 from * overlapping the maintenance area. */ for(i=0; i<8; i++) { if(rsp->nblocks) { pt_info[i].pt_nb = rsp->nblocks; pt_info[i].pt_sb = rsp->blkoff; } /* -1 and -2 mean the same thing here, see comment above */ if(rsp->nblocks < 0L) { pt_info[i].pt_nb = (long)ra_drv[ra_index[dip->di_cn]+unit].d_un.ra_dsize - (long)rsp->blkoff; /* * Don't subtract maintenance area if RX33 or RX50 disk */ if((dt_info[dip->di_dt[unit]].dt_flags&DI_RX50) == 0) pt_info[i].pt_nb -= ra_mas[dip->di_cn]; } rsp++; } nbpc = 0; break; case RL_BMAJ: /* all partitions (except RL02 partition 1) start at block 0 */ pt_info[7].pt_nb = (long)rl_dt[unit]; /* drive type = unit size */ pt_info[0].pt_nb = 10240L; /* RL01 & RL02 both use partition 0 */ if(rl_dt[unit] == RL02) { pt_info[1].pt_sb = 10240L; pt_info[1].pt_nb = 10240L; } return(0); case HX_BMAJ: /* if((dt_info[dip->di_dt[unit]].dt_flags&DI_SINGLE) == 1) */ if (hx_single == 1) pt_info[7].pt_nb = 500L; else /* normal RX02 double density */ pt_info[7].pt_nb = 1000L; return(0); case HP_BMAJ: case HM_BMAJ: case HJ_BMAJ: switch(dt_info[dip->di_dt[unit]].dt_type) { case RP04: case RP05: case RP06: nbpc = RP456_BPC; dsp = &hp_sizes; break; case RM02: case RM03: nbpc = RM23_BPC; dsp = &hp_sizes[8]; break; case RM05: nbpc = RM5_BPC; dsp = &hp_sizes[16]; break; case ML11: nbpc = 1; dsp = &hp_sizes[24]; break; default: /* THIS CAN'T HAPPEN */ printf("\n(spt) - unknown drive type!\n"); return(1); } break; case HK_BMAJ: nbpc = RK67_BPC; dsp = &hk_sizes; break; default: /* THIS CAN'T HAPPEN */ printf("\n(spt) - unknown controller type!\n"); return(1); } if(nbpc) /* get partition sizes, unless this is MSCP disk */ for(i=0; i<8; i++) { if(dsp->nblocks) { pt_info[i].pt_sb = (long)dsp->cyloff * (long)nbpc; pt_info[i].pt_nb = dsp->nblocks; } dsp++; } return(0); } /* * Return a pointer to a special device name string. * RAW /dev/r??## or /dev/r??# * BLK /dev/??## or /dev/??# */ char dsfname[15]; dsfn(mode, unit, fs, dip) register struct di_info *dip; int mode, unit, fs; { /* Non-Partitioned (RX02 or RK05) */ if(dt_info[dip->di_dt[unit]].dt_flags&DI_NPD) { /* if RX02 and not single density, bump unit number by 2 */ if((dt_info[dip->di_dt[unit]].dt_type == RX02) && (hx_single==0)) unit += 2; /* use double density */ sprintf(dsfname, "/dev%s%s%d", (mode==RAW) ? "/r" : "/", dip->di_name, unit); } /* change RX33/RX50 /dev/rd? to /dev/rx? */ else if(dt_info[dip->di_dt[unit]].dt_flags&DI_RX50) sprintf(dsfname, "/dev%s%s%d", (mode==RAW) ? "/r" : "/", "rx", unit); /* MSCP */ else if(dip->di_flags&DI_MSCP) sprintf(dsfname, "/dev%s%.2s%d%d", (mode==RAW) ? "/r" : "/", dt_info[dip->di_dt[unit]].dt_lname, unit, fs); /* all others */ else sprintf(dsfname, "/dev%s%s%d%d", (mode==RAW) ? "/r" : "/", dip->di_name, unit, fs); return(&dsfname); }