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