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