xref: /openbsd/sys/arch/alpha/stand/nboot/disk.c (revision 0eebeeb2)
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