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