Home | History | Annotate | Line # | Download | only in vax
      1 /*	$NetBSD: disksubr.c,v 1.55 2026/05/30 10:10:11 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
     32  */
     33 
     34 #include <sys/cdefs.h>
     35 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.55 2026/05/30 10:10:11 thorpej Exp $");
     36 
     37 #include "opt_compat_ultrix.h"
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/buf.h>
     42 #include <sys/cpu.h>
     43 #include <sys/disklabel.h>
     44 #include <sys/disk.h>
     45 #include <sys/syslog.h>
     46 #include <sys/proc.h>
     47 
     48 #include <uvm/uvm_extern.h>
     49 
     50 #include <machine/macros.h>
     51 
     52 #include <dev/mscp/mscp.h> /* For disk encoding scheme */
     53 
     54 #ifdef COMPAT_ULTRIX
     55 #include <dev/dec/dec_boot.h>
     56 #include <ufs/ufs/dinode.h>	/* XXX for fs.h */
     57 #include <ufs/ffs/fs.h>		/* XXX for BBSIZE & SBSIZE */
     58 
     59 static const char *compat_label(dev_t dev, void (*strat)(struct buf *bp),
     60 	struct disklabel *lp, struct cpu_disklabel *osdep);
     61 #endif /* COMPAT_ULTRIX */
     62 
     63 /*
     64  * Attempt to read a disk label from a device
     65  * using the indicated strategy routine.
     66  * The label must be partly set up before this:
     67  * secpercyl and anything required in the strategy routine
     68  * (e.g., sector size) must be filled in before calling us.
     69  * Returns null on success and an error string on failure.
     70  */
     71 const char *
     72 readdisklabel(dev_t dev, void (*strat)(struct buf *),
     73     struct disklabel *lp, struct cpu_disklabel *osdep)
     74 {
     75 	struct buf *bp;
     76 	struct disklabel *dlp;
     77 	const char *msg = NULL;
     78 
     79 	if (lp->d_npartitions == 0) { /* Assume no label */
     80 		lp->d_secperunit = 0x1fffffff;
     81 		lp->d_npartitions = 3;
     82 		lp->d_partitions[2].p_size = 0x1fffffff;
     83 		lp->d_partitions[2].p_offset = 0;
     84 	}
     85 
     86 	bp = geteblk((int)lp->d_secsize);
     87 	bp->b_dev = dev;
     88 	bp->b_blkno = LABELSECTOR;
     89 	bp->b_bcount = lp->d_secsize;
     90 	bp->b_flags |= B_READ;
     91 	bp->b_cylinder = LABELSECTOR / lp->d_secpercyl;
     92 	(*strat)(bp);
     93 	if (biowait(bp)) {
     94 		msg = "I/O error";
     95 	} else {
     96 		dlp = (struct disklabel *)((char *)bp->b_data + LABELOFFSET);
     97 		if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
     98 			msg = "no disk label";
     99 		} else if (dlp->d_npartitions > MAXPARTITIONS ||
    100 		    dkcksum(dlp) != 0)
    101 			msg = "disk label corrupted";
    102 		else {
    103 			*lp = *dlp;
    104 		}
    105 	}
    106 	brelse(bp, 0);
    107 
    108 #ifdef COMPAT_ULTRIX
    109 	/*
    110 	 * If no NetBSD label was found, check for an Ultrix label and
    111 	 * construct tne incore label from the Ultrix partition information.
    112 	 */
    113 	if (msg != NULL) {
    114 		msg = compat_label(dev, strat, lp, osdep);
    115 		if (msg == NULL) {
    116 			printf("WARNING: using Ultrix partition information\n");
    117 			/* set geometry? */
    118 		}
    119 	}
    120 #endif
    121 	return (msg);
    122 }
    123 
    124 #ifdef COMPAT_ULTRIX
    125 /*
    126  * Given a buffer bp, try and interpret it as an Ultrix disk label,
    127  * putting the partition info into a native NetBSD label
    128  */
    129 const char *
    130 compat_label(dev_t dev, void (*strat)(struct buf *bp), struct disklabel *lp,
    131 	struct cpu_disklabel *osdep)
    132 {
    133 	dec_disklabel *dlp;
    134 	struct buf *bp = NULL;
    135 	const char *msg = NULL;
    136 	uint8_t *dp;
    137 
    138 	bp = geteblk((int)lp->d_secsize);
    139 	dp = bp->b_data;
    140 	bp->b_dev = dev;
    141 	bp->b_blkno = DEC_LABEL_SECTOR;
    142 	bp->b_bcount = lp->d_secsize;
    143 	bp->b_flags |= B_READ;
    144 	bp->b_cylinder = DEC_LABEL_SECTOR / lp->d_secpercyl;
    145 	(*strat)(bp);
    146 
    147 	if (biowait(bp)) {
    148 		msg = "I/O error";
    149 		goto done;
    150 	}
    151 
    152 	for (dlp = (dec_disklabel *)dp;
    153 	    dlp <= (dec_disklabel *)(dp+DEV_BSIZE-sizeof(*dlp));
    154 	    dlp = (dec_disklabel *)((char *)dlp + sizeof(long))) {
    155 
    156 		int part;
    157 
    158 		if (dlp->magic != DEC_LABEL_MAGIC) {
    159 			if (dlp->magic != 0)
    160 				printf("label: %x\n",dlp->magic);
    161 			msg = ((msg != NULL) ? msg: "no disk label");
    162 			goto done;
    163 		}
    164 
    165 		lp->d_magic = DEC_LABEL_MAGIC;
    166 		lp->d_npartitions = 0;
    167 		strncpy(lp->d_packname, "Ultrix label", 16);
    168 		lp->d_rpm = 3600;
    169 		lp->d_interleave = 1;
    170 		lp->d_flags = 0;
    171 		lp->d_bbsize = BBSIZE;
    172 		lp->d_sbsize = 8192;
    173 		for (part = 0;
    174 		     part <((MAXPARTITIONS<DEC_NUM_DISK_PARTS) ?
    175 		            MAXPARTITIONS : DEC_NUM_DISK_PARTS);
    176 		     part++) {
    177 			lp->d_partitions[part].p_size = dlp->map[part].num_blocks;
    178 			lp->d_partitions[part].p_offset = dlp->map[part].start_block;
    179 			lp->d_partitions[part].p_fsize = 1024;
    180 			lp->d_partitions[part].p_fstype =
    181 			    (part==1) ? FS_SWAP : FS_BSDFFS;
    182 			lp->d_npartitions += 1;
    183 
    184 #ifdef DIAGNOSTIC
    185 			printf(" Ultrix label rz%d%c: start %d len %d\n",
    186 			       DISKUNIT(dev), "abcdefgh"[part],
    187 			       lp->d_partitions[part].p_offset,
    188 			       lp->d_partitions[part].p_size);
    189 #endif
    190 		}
    191 		break;
    192 	}
    193 
    194 done:
    195 	brelse(bp, 0);
    196 	return (msg);
    197 }
    198 #endif /* COMPAT_ULTRIX */
    199 
    200 /*
    201  * Write disk label back to device after modification.
    202  * Always allow writing of disk label; even if the disk is unlabeled.
    203  */
    204 int
    205 writedisklabel(dev_t dev, void (*strat)(struct buf *),
    206     struct disklabel *lp, struct cpu_disklabel *osdep)
    207 {
    208 	struct buf *bp;
    209 	struct disklabel *dlp;
    210 	int error = 0;
    211 
    212 	bp = geteblk((int)lp->d_secsize);
    213 	bp->b_dev = MAKEDISKDEV(major(dev), DISKUNIT(dev), RAW_PART);
    214 	bp->b_blkno = LABELSECTOR;
    215 	bp->b_bcount = lp->d_secsize;
    216 	bp->b_flags |= B_READ;
    217 	(*strat)(bp);
    218 	if ((error = biowait(bp)))
    219 		goto done;
    220 	dlp = (struct disklabel *)((char *)bp->b_data + LABELOFFSET);
    221 	memcpy(dlp, lp, sizeof(struct disklabel));
    222 	bp->b_oflags &= ~(BO_DONE);
    223 	bp->b_flags &= ~(B_READ);
    224 	bp->b_flags |= B_WRITE;
    225 	(*strat)(bp);
    226 	error = biowait(bp);
    227 
    228 done:
    229 	brelse(bp, 0);
    230 	return (error);
    231 }
    232 
    233 /*
    234  * Print out the name of the device; ex. TK50, RA80. DEC uses a common
    235  * disk type encoding scheme for most of its disks.
    236  */
    237 void
    238 disk_printtype(int unit, int type)
    239 {
    240 	printf(" drive %d: %c%c", unit, (int)MSCP_MID_CHAR(2, type),
    241 	    (int)MSCP_MID_CHAR(1, type));
    242 	if (MSCP_MID_ECH(0, type))
    243 		printf("%c", (int)MSCP_MID_CHAR(0, type));
    244 	printf("%d\n", MSCP_MID_NUM(type));
    245 }
    246 
    247 /*
    248  * Be sure that the pages we want to do DMA to is actually there
    249  * by faking page-faults if necessary. If given a map-register address,
    250  * also map it in.
    251  */
    252 void
    253 disk_reallymapin(struct buf *bp, struct pte *map, int reg, int flag)
    254 {
    255 	struct proc *p;
    256 	volatile pt_entry_t *io;
    257 	pt_entry_t *pte;
    258 	int pfnum, npf, o;
    259 	void *addr;
    260 
    261 	o = (int)bp->b_data & VAX_PGOFSET;
    262 	npf = vax_btoc(bp->b_bcount + o) + 1;
    263 	addr = bp->b_data;
    264 	p = bp->b_proc;
    265 
    266 	/*
    267 	 * Get a pointer to the pte pointing out the first virtual address.
    268 	 * Use different ways in kernel and user space.
    269 	 */
    270 	if ((bp->b_flags & B_PHYS) == 0) {
    271 		pte = kvtopte(addr);
    272 		if (p == 0)
    273 			p = &proc0;
    274 	} else {
    275 		long xaddr = (long)addr;
    276 		if (xaddr & 0x40000000)
    277 			pte = &p->p_vmspace->vm_map.pmap->pm_p1br[xaddr &
    278 			    ~0x40000000];
    279 		else
    280 			pte = &p->p_vmspace->vm_map.pmap->pm_p0br[xaddr];
    281 	}
    282 
    283 	if (map) {
    284 		io = &map[reg];
    285 		while (--npf > 0) {
    286 			pfnum = pte->pg_pfn;
    287 			if (pfnum == 0)
    288 				panic("mapin zero entry");
    289 			pte++;
    290 			*(volatile int *)io++ = pfnum | flag;
    291 		}
    292 		*(volatile int *)io = 0;
    293 	}
    294 }
    295