1 /* $OpenBSD: disk.c,v 1.11 2003/06/02 23:27:44 millert Exp $ */ 2 /* $NetBSD: disk.c,v 1.6 1997/04/06 08:40:33 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)rz.c 8.1 (Berkeley) 6/10/93 36 */ 37 38 #include <lib/libsa/stand.h> 39 40 #include <sys/param.h> 41 #include <sys/disklabel.h> 42 43 #include <machine/rpb.h> 44 #include <machine/prom.h> 45 46 #include "disk.h" 47 48 struct disk_softc { 49 int sc_fd; /* PROM channel number */ 50 int sc_ctlr; /* controller number */ 51 int sc_unit; /* disk unit number */ 52 int sc_part; /* disk partition number */ 53 struct disklabel sc_label; /* disk label for this disk */ 54 }; 55 56 int 57 diskstrategy(devdata, rw, bn, reqcnt, addrvoid, cnt) 58 void *devdata; 59 int rw; 60 daddr_t bn; 61 size_t reqcnt; 62 void *addrvoid; 63 size_t *cnt; /* out: number of bytes transferred */ 64 { 65 char *addr = addrvoid; 66 struct disk_softc *sc; 67 struct partition *pp; 68 prom_return_t ret; 69 int s; 70 71 if ((reqcnt & 0xffffff) != reqcnt || 72 reqcnt == 0) 73 asm("call_pal 0"); 74 75 twiddle(); 76 77 /* Partial-block transfers not handled. */ 78 if (reqcnt & (DEV_BSIZE - 1)) { 79 *cnt = 0; 80 return (EINVAL); 81 } 82 83 sc = (struct disk_softc *)devdata; 84 pp = &sc->sc_label.d_partitions[sc->sc_part]; 85 86 ret.bits = prom_read(sc->sc_fd, reqcnt, addr, bn + pp->p_offset); 87 if (ret.u.status) 88 return (EIO); 89 *cnt = ret.u.retval; 90 return (0); 91 } 92 93 int 94 diskopen(f, ctlr, unit, part) 95 struct open_file *f; 96 int ctlr, unit, part; 97 { 98 struct disklabel *lp; 99 prom_return_t ret; 100 size_t cnt; 101 int devlen, i; 102 char *msg, buf[DEV_BSIZE], devname[32]; 103 struct disk_softc *sc; 104 105 if (unit >= 16 || part >= MAXPARTITIONS) 106 return (ENXIO); 107 /* 108 * XXX 109 * We don't know what device names look like yet, 110 * so we can't change them. 111 */ 112 ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname)); 113 devlen = ret.u.retval; 114 115 ret.bits = prom_open(devname, devlen); 116 if (ret.u.status == 2) 117 return (ENXIO); 118 if (ret.u.status == 3) 119 return (EIO); 120 121 sc = alloc(sizeof(struct disk_softc)); 122 bzero(sc, sizeof(struct disk_softc)); 123 f->f_devdata = (void *)sc; 124 125 sc->sc_fd = ret.u.retval; 126 sc->sc_ctlr = ctlr; 127 sc->sc_unit = unit; 128 sc->sc_part = part; 129 130 /* Try to read disk label and partition table information. */ 131 lp = &sc->sc_label; 132 lp->d_secsize = DEV_BSIZE; 133 lp->d_secpercyl = 1; 134 lp->d_npartitions = MAXPARTITIONS; 135 lp->d_partitions[part].p_offset = 0; 136 lp->d_partitions[part].p_size = 0x7fffffff; 137 i = diskstrategy(sc, F_READ, 138 (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt); 139 if (i || cnt != DEV_BSIZE) { 140 printf("disk%d: error reading disk label\n", unit); 141 goto bad; 142 } else if (((struct disklabel *)(buf + LABELOFFSET))->d_magic != 143 DISKMAGIC) { 144 /* No label at all. Fake all partitions as whole disk. */ 145 for (i = 0; i < MAXPARTITIONS; i++) { 146 lp->d_partitions[part].p_offset = 0; 147 lp->d_partitions[part].p_size = 0x7fffffff; 148 } 149 } else { 150 msg = getdisklabel(buf + LABELOFFSET, lp); 151 if (msg) { 152 printf("disk%d: %s\n", unit, msg); 153 goto bad; 154 } 155 } 156 157 if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) { 158 bad: free(sc, sizeof(struct disk_softc)); 159 return (ENXIO); 160 } 161 return (0); 162 } 163 164 diskclose(f) 165 struct open_file *f; 166 { 167 struct disk_softc *sc; 168 169 sc = f->f_devdata; 170 (void)prom_close(sc->sc_fd); 171 172 free(sc, sizeof(struct disk_softc)); 173 f->f_devdata = NULL; 174 return (0); 175 } 176