Home | History | Annotate | Line # | Download | only in boot
disk.c revision 1.2.4.1
      1  1.2.4.1     yamt /*	$NetBSD: disk.c,v 1.2.4.1 2006/06/21 14:49:08 yamt Exp $	*/
      2      1.1  tsutsui 
      3      1.1  tsutsui /*
      4      1.1  tsutsui  * Copyright (c) 1992, 1993
      5      1.1  tsutsui  *	The Regents of the University of California.  All rights reserved.
      6      1.1  tsutsui  *
      7      1.1  tsutsui  * This code is derived from software contributed to Berkeley by
      8      1.1  tsutsui  * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
      9      1.1  tsutsui  *
     10      1.1  tsutsui  * Redistribution and use in source and binary forms, with or without
     11      1.1  tsutsui  * modification, are permitted provided that the following conditions
     12      1.1  tsutsui  * are met:
     13      1.1  tsutsui  * 1. Redistributions of source code must retain the above copyright
     14      1.1  tsutsui  *    notice, this list of conditions and the following disclaimer.
     15      1.1  tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1  tsutsui  *    notice, this list of conditions and the following disclaimer in the
     17      1.1  tsutsui  *    documentation and/or other materials provided with the distribution.
     18      1.1  tsutsui  * 3. Neither the name of the University nor the names of its contributors
     19      1.1  tsutsui  *    may be used to endorse or promote products derived from this software
     20      1.1  tsutsui  *    without specific prior written permission.
     21      1.1  tsutsui  *
     22      1.1  tsutsui  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23      1.1  tsutsui  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24      1.1  tsutsui  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25      1.1  tsutsui  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26      1.1  tsutsui  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27      1.1  tsutsui  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28      1.1  tsutsui  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29      1.1  tsutsui  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30      1.1  tsutsui  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31      1.1  tsutsui  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32      1.1  tsutsui  * SUCH DAMAGE.
     33      1.1  tsutsui  *
     34      1.1  tsutsui  *	@(#)disk.c	8.1 (Berkeley) 6/10/93
     35      1.1  tsutsui  */
     36      1.1  tsutsui 
     37      1.1  tsutsui #include <lib/libsa/stand.h>
     38      1.1  tsutsui #include <machine/stdarg.h>
     39      1.1  tsutsui 
     40      1.1  tsutsui #include <sys/param.h>
     41      1.1  tsutsui #include <sys/disklabel.h>
     42      1.1  tsutsui 
     43      1.1  tsutsui #include <dev/arcbios/arcbios.h>
     44      1.1  tsutsui 
     45      1.1  tsutsui #include "common.h"
     46      1.1  tsutsui #include "disk.h"
     47      1.1  tsutsui 
     48      1.1  tsutsui #define	RF_PROTECTED_SECTORS	64	/* XXX refer to <.../rf_optnames.h> */
     49      1.1  tsutsui 
     50      1.1  tsutsui extern const struct arcbios_fv *ARCBIOS;
     51      1.1  tsutsui 
     52      1.1  tsutsui struct	disk_softc {
     53      1.1  tsutsui 	u_long	sc_fd;			/* ARCBIOS file id */
     54      1.1  tsutsui 	int	sc_part;		/* disk partition number */
     55      1.1  tsutsui 	struct	disklabel sc_label;	/* disk label for this disk */
     56      1.1  tsutsui };
     57      1.1  tsutsui 
     58      1.1  tsutsui int
     59      1.1  tsutsui diskstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addr,
     60      1.1  tsutsui     size_t *cnt)
     61      1.1  tsutsui {
     62      1.1  tsutsui 	struct disk_softc *sc = (struct disk_softc *)devdata;
     63      1.1  tsutsui 	int part = sc->sc_part;
     64      1.1  tsutsui 	struct partition *pp = &sc->sc_label.d_partitions[part];
     65      1.1  tsutsui 	long error;
     66      1.1  tsutsui 	int64_t offset;
     67      1.1  tsutsui 	u_long count;
     68      1.1  tsutsui 
     69      1.1  tsutsui 	offset = bn;
     70      1.1  tsutsui 
     71      1.1  tsutsui 	/*
     72      1.1  tsutsui 	 * Partial-block transfers not handled.
     73      1.1  tsutsui 	 */
     74      1.1  tsutsui 	if (reqcnt & (DEV_BSIZE - 1)) {
     75      1.1  tsutsui 		*cnt = 0;
     76      1.1  tsutsui 		return EINVAL;
     77      1.1  tsutsui 	}
     78      1.1  tsutsui 
     79      1.1  tsutsui 	offset += pp->p_offset;
     80      1.1  tsutsui 
     81      1.1  tsutsui 	if (pp->p_fstype == FS_RAID)
     82      1.1  tsutsui 		offset += RF_PROTECTED_SECTORS;
     83      1.1  tsutsui 
     84      1.1  tsutsui 	/*
     85      1.1  tsutsui 	 * Convert from blocks to bytes.
     86      1.1  tsutsui 	 */
     87      1.1  tsutsui 	offset *= DEV_BSIZE;
     88      1.1  tsutsui 
     89      1.1  tsutsui 	error = (*ARCBIOS->Seek)(sc->sc_fd, &offset, 0);
     90      1.1  tsutsui 	if (error != ARCBIOS_ESUCCESS)
     91      1.1  tsutsui 		return EIO;
     92      1.1  tsutsui 	error = (*ARCBIOS->Read)(sc->sc_fd, addr, reqcnt, &count);
     93      1.1  tsutsui 	if (error != ARCBIOS_ESUCCESS)
     94      1.1  tsutsui 		return EIO;
     95      1.1  tsutsui 
     96      1.1  tsutsui 	*cnt = count;
     97      1.1  tsutsui 	return 0;
     98      1.1  tsutsui }
     99      1.1  tsutsui 
    100      1.1  tsutsui int
    101      1.1  tsutsui diskopen(struct open_file *f, ...)
    102      1.1  tsutsui {
    103      1.1  tsutsui 	int part;
    104      1.1  tsutsui 
    105      1.1  tsutsui 	struct disk_softc *sc;
    106      1.1  tsutsui 	struct disklabel *lp;
    107      1.1  tsutsui #ifdef arc
    108      1.1  tsutsui 	char *msg, buf[DEV_BSIZE];
    109      1.1  tsutsui 	size_t cnt;
    110      1.1  tsutsui 	int mbrp_off, i;
    111      1.1  tsutsui #endif
    112      1.1  tsutsui 	int error;
    113      1.1  tsutsui 	u_long fd;
    114      1.1  tsutsui 	char *device;
    115      1.1  tsutsui 	va_list ap;
    116      1.1  tsutsui 
    117      1.1  tsutsui 	va_start(ap, f);
    118      1.1  tsutsui 
    119      1.1  tsutsui 	device = va_arg(ap, char *);
    120      1.1  tsutsui 
    121      1.1  tsutsui 	/*
    122      1.1  tsutsui 	 * For NetBSD/sgimips, since we use the SGI partition map directly,
    123      1.1  tsutsui 	 * we fake an in-core NetBSD disklabel with offset of 0.
    124      1.1  tsutsui 	 *
    125      1.1  tsutsui 	 * For NetBSD/arc, there is a MBR partition map on the disk, which we
    126      1.1  tsutsui 	 * then expect to find a NetBSD disklabel within the MBR partition.
    127      1.1  tsutsui 	 * We require that the kernel be located in first partition in the
    128      1.1  tsutsui 	 * NetBSD disklabel, because we have not other way to represent the
    129      1.1  tsutsui 	 * root partition.
    130      1.1  tsutsui 	 */
    131      1.1  tsutsui 	part = 0;
    132      1.1  tsutsui 
    133      1.1  tsutsui 	if (part >= MAXPARTITIONS)
    134      1.1  tsutsui 		return ENXIO;
    135      1.1  tsutsui 
    136      1.1  tsutsui 	error = (*ARCBIOS->Open)(device, 0, &fd);
    137      1.1  tsutsui 	if (error) {
    138      1.1  tsutsui 		printf("diskopen: open failed, errno = %d\n", error);
    139      1.1  tsutsui 		return ENXIO;
    140      1.1  tsutsui 	}
    141      1.1  tsutsui 
    142      1.1  tsutsui 	sc = alloc(sizeof(struct disk_softc));
    143      1.1  tsutsui 	memset(sc, 0, sizeof(struct disk_softc));
    144      1.1  tsutsui 	f->f_devdata = (void *)sc;
    145      1.1  tsutsui 
    146      1.1  tsutsui 	sc->sc_fd = fd;
    147      1.1  tsutsui 	sc->sc_part = part;
    148      1.1  tsutsui 
    149      1.1  tsutsui 	/* try to read disk label and partition table information */
    150      1.1  tsutsui 	lp = &sc->sc_label;
    151      1.1  tsutsui 	lp->d_secsize = DEV_BSIZE;
    152      1.1  tsutsui 	lp->d_secpercyl = 1;
    153      1.1  tsutsui 	lp->d_npartitions = MAXPARTITIONS;
    154      1.1  tsutsui 	lp->d_partitions[part].p_offset = 0;
    155      1.1  tsutsui 	lp->d_partitions[part].p_size = 0x7fffffff;
    156      1.1  tsutsui 
    157      1.1  tsutsui #ifdef arc
    158      1.1  tsutsui 	error = diskstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE,
    159      1.1  tsutsui 	    buf, &cnt);
    160      1.1  tsutsui 	if (error || cnt != DEV_BSIZE) {
    161      1.1  tsutsui 		printf("%s: can't read disklabel, errno = %d\n",
    162      1.1  tsutsui 		    device, error);
    163  1.2.4.1     yamt 		dealloc(sc, sizeof(struct disk_softc));
    164      1.1  tsutsui 		return ENXIO;
    165      1.1  tsutsui 	}
    166      1.1  tsutsui 	msg = getdisklabel(buf, lp);
    167      1.1  tsutsui 	if (msg) {
    168      1.1  tsutsui 		/* If no label, just assume 0 and return */
    169      1.1  tsutsui 		return 0;
    170      1.1  tsutsui 	}
    171      1.1  tsutsui 
    172      1.1  tsutsui 	/*
    173      1.1  tsutsui 	 * On arc, we can't open whole disk, but can open each partition with
    174      1.1  tsutsui 	 * OSLOADPARTITION like scsi(0)disk(0)rdisk()partition(1) etc.
    175      1.1  tsutsui 	 * Thus, we don't have to add offset of the MBR partition.
    176      1.1  tsutsui 	 */
    177      1.1  tsutsui 	/* XXX magic: partition 2 is whole NetBSD partition */
    178      1.1  tsutsui 	mbrp_off = lp->d_partitions[2].p_offset;
    179      1.1  tsutsui 	for (i = 0; i < MAXPARTITIONS; i++) {
    180      1.1  tsutsui 		if (lp->d_partitions[i].p_fstype != FS_UNUSED &&
    181      1.1  tsutsui 		    lp->d_partitions[i].p_offset >= mbrp_off)
    182      1.1  tsutsui 			lp->d_partitions[i].p_offset -= mbrp_off;
    183      1.1  tsutsui 	}
    184      1.1  tsutsui 
    185      1.1  tsutsui 	if (part >= lp->d_npartitions ||
    186      1.1  tsutsui 	    lp->d_partitions[part].p_fstype == FS_UNUSED ||
    187      1.1  tsutsui 	    lp->d_partitions[part].p_size == 0) {
    188  1.2.4.1     yamt 		dealloc(sc, sizeof(struct disk_softc));
    189      1.1  tsutsui 		return ENXIO;
    190      1.1  tsutsui 	}
    191      1.2  tsutsui #endif
    192      1.1  tsutsui 	return 0;
    193      1.1  tsutsui }
    194      1.1  tsutsui 
    195      1.1  tsutsui #ifndef LIBSA_NO_DEV_CLOSE
    196      1.1  tsutsui int
    197      1.1  tsutsui diskclose(struct open_file *f)
    198      1.1  tsutsui {
    199      1.1  tsutsui 
    200      1.1  tsutsui 	(*ARCBIOS->Close)(((struct disk_softc *)(f->f_devdata))->sc_fd);
    201  1.2.4.1     yamt 	dealloc(f->f_devdata, sizeof(struct disk_softc));
    202      1.1  tsutsui 	f->f_devdata = NULL;
    203      1.1  tsutsui 	return 0;
    204      1.1  tsutsui }
    205      1.1  tsutsui #endif
    206