1 /* $OpenBSD: disk.c,v 1.1 2023/03/11 20:56:01 miod 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 "libsa.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 struct disk_softc {
47 int sc_fd; /* PROM channel number */
48 int sc_part; /* disk partition number */
49 struct disklabel sc_label; /* disk label for this disk */
50 };
51
52 int
diskstrategy(void * devdata,int rw,daddr_t bn,size_t reqcnt,void * addrvoid,size_t * cnt)53 diskstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addrvoid,
54 size_t *cnt)
55 {
56 char *addr = addrvoid;
57 struct disk_softc *sc;
58 struct partition *pp;
59 prom_return_t ret;
60 int s;
61
62 #ifdef DEBUG
63 if ((reqcnt & 0xffffff) != reqcnt || reqcnt == 0)
64 asm("call_pal 0");
65 #endif
66
67 twiddle();
68
69 /* Partial-block transfers not handled. */
70 if (reqcnt & (DEV_BSIZE - 1)) {
71 *cnt = 0;
72 return (EINVAL);
73 }
74
75 sc = (struct disk_softc *)devdata;
76 pp = &sc->sc_label.d_partitions[sc->sc_part];
77 bn += DL_GETPOFFSET(pp);
78
79 if (rw == F_READ)
80 ret.bits = prom_read(sc->sc_fd, reqcnt, addr, bn);
81 else
82 ret.bits = prom_write(sc->sc_fd, reqcnt, addr, bn);
83 if (ret.u.status)
84 return (EIO);
85 if (cnt)
86 *cnt = ret.u.retval;
87 return (0);
88 }
89
90 int
diskopen(struct open_file * f,...)91 diskopen(struct open_file *f, ...)
92 {
93 struct disklabel *lp;
94 prom_return_t ret;
95 size_t cnt, devlen;
96 int i;
97 char *msg, buf[DEV_BSIZE];
98 struct disk_softc *sc;
99 va_list ap;
100 unsigned int part = 0;
101 char devname[128];
102
103 /* See devopen() - we always use the device we're booted off here. */
104 ret.bits = prom_getenv(PROM_E_BOOTED_DEV, devname, sizeof(devname));
105 devlen = ret.u.retval;
106
107 ret.bits = prom_open((u_int64_t)devname, devlen);
108 if (ret.u.status == 2)
109 return (ENXIO);
110 if (ret.u.status == 3)
111 return (EIO);
112
113 sc = alloc(sizeof(struct disk_softc));
114 bzero(sc, sizeof(struct disk_softc));
115 f->f_devdata = (void *)sc;
116
117 sc->sc_fd = ret.u.retval;
118 sc->sc_part = part;
119
120 /* Try to read disk label and partition table information. */
121 lp = &sc->sc_label;
122 lp->d_secsize = DEV_BSIZE;
123 lp->d_secpercyl = 1;
124 lp->d_npartitions = MAXPARTITIONS;
125 DL_SETPOFFSET(&lp->d_partitions[part], 0);
126 DL_SETPSIZE(&lp->d_partitions[part], -1LL);
127 i = diskstrategy(sc, F_READ, LABELSECTOR, DEV_BSIZE, buf, &cnt);
128 if (i || cnt != DEV_BSIZE) {
129 printf("%s: error reading disk label\n", __func__);
130 goto bad;
131 } else if (((struct disklabel *)(buf + LABELOFFSET))->d_magic !=
132 DISKMAGIC) {
133 /* No label at all. Fake all partitions as whole disk. */
134 for (i = 0; i < MAXPARTITIONS; i++) {
135 DL_SETPOFFSET(&lp->d_partitions[part], 0);
136 DL_SETPSIZE(&lp->d_partitions[part], -1LL);
137 }
138 } else {
139 msg = getdisklabel(buf + LABELOFFSET, lp);
140 if (msg) {
141 printf("%s: %s\n", __func__, msg);
142 goto bad;
143 }
144 }
145
146 if (part >= lp->d_npartitions ||
147 DL_GETPSIZE(&lp->d_partitions[part]) == 0) {
148 bad:
149 free(sc, sizeof(struct disk_softc));
150 return (ENXIO);
151 }
152 return (0);
153 }
154
155 int
diskclose(struct open_file * f)156 diskclose(struct open_file *f)
157 {
158 struct disk_softc *sc;
159
160 sc = f->f_devdata;
161 (void)prom_close(sc->sc_fd);
162
163 free(sc, sizeof(struct disk_softc));
164 f->f_devdata = NULL;
165 return (0);
166 }
167