1 /* $OpenBSD: disk.c,v 1.19 2020/12/09 18:10:17 krw 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(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addrvoid, 58 size_t *cnt) 59 { 60 char *addr = addrvoid; 61 struct disk_softc *sc; 62 struct partition *pp; 63 prom_return_t ret; 64 int s; 65 66 if ((reqcnt & 0xffffff) != reqcnt || 67 reqcnt == 0) 68 asm("call_pal 0"); 69 70 twiddle(); 71 72 /* Partial-block transfers not handled. */ 73 if (reqcnt & (DEV_BSIZE - 1)) { 74 *cnt = 0; 75 return (EINVAL); 76 } 77 78 sc = (struct disk_softc *)devdata; 79 pp = &sc->sc_label.d_partitions[sc->sc_part]; 80 81 if (rw == F_READ) 82 ret.bits = prom_read(sc->sc_fd, reqcnt, addr, bn + pp->p_offset); 83 else 84 ret.bits = prom_write(sc->sc_fd, reqcnt, addr, bn + pp->p_offset); 85 if (ret.u.status) 86 return (EIO); 87 if (cnt) 88 *cnt = ret.u.retval; 89 return (0); 90 } 91 92 int 93 diskopen(struct open_file *f, int ctlr, int unit, int part) 94 { 95 struct disklabel *lp; 96 prom_return_t ret; 97 size_t cnt; 98 int devlen, i; 99 char *msg, buf[DEV_BSIZE], devname[32]; 100 struct disk_softc *sc; 101 102 if (unit >= 16 || part >= MAXPARTITIONS) 103 return (ENXIO); 104 /* 105 * XXX 106 * We don't know what device names look like yet, 107 * so we can't change them. 108 */ 109 ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname)); 110 devlen = ret.u.retval; 111 112 ret.bits = prom_open(devname, devlen); 113 if (ret.u.status == 2) 114 return (ENXIO); 115 if (ret.u.status == 3) 116 return (EIO); 117 118 sc = alloc(sizeof(struct disk_softc)); 119 bzero(sc, sizeof(struct disk_softc)); 120 f->f_devdata = (void *)sc; 121 122 sc->sc_fd = ret.u.retval; 123 sc->sc_ctlr = ctlr; 124 sc->sc_unit = unit; 125 sc->sc_part = part; 126 127 /* Try to read disk label and partition table information. */ 128 lp = &sc->sc_label; 129 lp->d_secsize = DEV_BSIZE; 130 lp->d_secpercyl = 1; 131 lp->d_npartitions = MAXPARTITIONS; 132 DL_SETPOFFSET(&lp->d_partitions[part], 0); 133 DL_SETPSIZE(&lp->d_partitions[part], 0x7fffffff); 134 i = diskstrategy(sc, F_READ, 135 LABELSECTOR, DEV_BSIZE, buf, &cnt); 136 if (i || cnt != DEV_BSIZE) { 137 printf("disk%d: error reading disk label\n", unit); 138 goto bad; 139 } else if (((struct disklabel *)(buf + LABELOFFSET))->d_magic != 140 DISKMAGIC) { 141 /* No label at all. Fake all partitions as whole disk. */ 142 for (i = 0; i < MAXPARTITIONS; i++) { 143 DL_SETPOFFSET(&lp->d_partitions[part], 0); 144 DL_SETPSIZE(&lp->d_partitions[part], 0x7fffffff); 145 } 146 } else { 147 msg = getdisklabel(buf + LABELOFFSET, lp); 148 if (msg) { 149 printf("disk%d: %s\n", unit, msg); 150 goto bad; 151 } 152 } 153 154 if (part >= lp->d_npartitions || 155 DL_GETPSIZE(&lp->d_partitions[part]) == 0) { 156 bad: free(sc, sizeof(struct disk_softc)); 157 return (ENXIO); 158 } 159 return (0); 160 } 161 162 int 163 diskclose(struct open_file *f) 164 { 165 struct disk_softc *sc; 166 167 sc = f->f_devdata; 168 (void)prom_close(sc->sc_fd); 169 170 free(sc, sizeof(struct disk_softc)); 171 f->f_devdata = NULL; 172 return (0); 173 } 174