1/*	$NetBSD: rz.c,v 1.25 2009/03/14 21:04:14 dsl Exp $	*/
2
3/*
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Van Jacobson of Lawrence Berkeley Laboratory and Ralph Campbell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)rz.c	8.1 (Berkeley) 6/10/93
35 */
36
37#include <lib/libsa/stand.h>
38#include <lib/libkern/libkern.h>
39#include <machine/dec_prom.h>
40
41#include <sys/param.h>
42#include <sys/disklabel.h>
43
44#include "common.h"
45#include "rz.h"
46
47#define	RF_PROTECTED_SECTORS	64	/* XXX refer to <.../rf_optnames.h> */
48
49
50struct	rz_softc {
51	int	sc_fd;			/* PROM file id */
52	int	sc_ctlr;		/* controller number */
53	int	sc_unit;		/* disk unit number */
54	int	sc_part;		/* disk partition number */
55	struct	disklabel sc_label;	/* disk label for this disk */
56};
57
58int
59rzstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addr, size_t *cnt)
60	/* cnt:	 out: number of bytes transfered */
61{
62	struct rz_softc *sc = (struct rz_softc *)devdata;
63	int part = sc->sc_part;
64	struct partition *pp = &sc->sc_label.d_partitions[part];
65	int s;
66	long offset;
67
68	offset = bn;
69
70	/*
71	 * Partial-block transfers not handled.
72	 */
73	if (reqcnt & (DEV_BSIZE - 1)) {
74		*cnt = 0;
75		return (EINVAL);
76	}
77
78	offset += pp->p_offset;
79
80	if (pp->p_fstype == FS_RAID)
81		offset += RF_PROTECTED_SECTORS;
82
83	/*
84	 * Convert from blocks to bytes.
85	 */
86	offset *= DEV_BSIZE;
87
88	if (callv == &callvec) {
89		/* No REX on this machine */
90		if (prom_lseek(sc->sc_fd, offset, 0) < 0)
91			return (EIO);
92		s = prom_read(sc->sc_fd, addr, reqcnt);
93	} else
94		s = bootread (offset / 512, addr, reqcnt);
95	if (s < 0)
96		return (EIO);
97
98	*cnt = s;
99	return (0);
100}
101
102int
103rzopen(struct open_file *f, ...)
104{
105	int ctlr, unit, part;
106
107	struct rz_softc *sc;
108	struct disklabel *lp;
109	int i;
110	char *msg;
111	char buf[DEV_BSIZE];
112	size_t cnt;
113	static char device[] = "rz(0,0,0)";
114	va_list ap;
115
116	va_start(ap, f);
117
118	ctlr = va_arg(ap, int);
119	unit = va_arg(ap, int);
120	part = va_arg(ap, int);
121	va_end(ap);
122	if (unit >= 8 || part >= 8)
123		return (ENXIO);
124	device[5] = '0' + unit;
125	/* NOTE: only support reads for now */
126	/* Another NOTE: bootinit on the TurboChannel doesn't look at
127	   the device string - it's provided for compatibility with
128	   the DS3100 PROMs.   As a consequence, it may be possible to
129	   boot from some other drive with these bootblocks on the 3100,
130	   but will not be possible on any TurboChannel machine. */
131
132	if (callv == &callvec)
133		i = prom_open(device, 0);
134	else
135		i = bootinit (device);
136	if (i < 0) {
137		printf("open failed\n");
138		return (ENXIO);
139	}
140
141	sc = alloc(sizeof(struct rz_softc));
142	memset(sc, 0, sizeof(struct rz_softc));
143	f->f_devdata = (void *)sc;
144
145	sc->sc_fd = i;
146	sc->sc_ctlr = ctlr;
147	sc->sc_unit = unit;
148	sc->sc_part = part;
149
150	/* try to read disk label and partition table information */
151	lp = &sc->sc_label;
152	lp->d_secsize = DEV_BSIZE;
153	lp->d_secpercyl = 1;
154	lp->d_npartitions = MAXPARTITIONS;
155	lp->d_partitions[part].p_offset = 0;
156	lp->d_partitions[part].p_size = 0x7fffffff;
157
158	i = rzstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE, buf, &cnt);
159	if (i || cnt != DEV_BSIZE) {
160		/* printf("rz%d: error reading disk label\n", unit); */
161		goto bad;
162	}
163	msg = getdisklabel(buf, lp);
164	if (msg) {
165		/* If no label, just assume 0 and return */
166		return (0);
167	}
168
169	if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0) {
170	bad:
171		dealloc(sc, sizeof(struct rz_softc));
172		return (ENXIO);
173	}
174	return (0);
175}
176
177#ifndef LIBSA_NO_DEV_CLOSE
178int
179rzclose(struct open_file *f)
180{
181	if (callv == &callvec)
182		prom_close(((struct rz_softc *)f->f_devdata)->sc_fd);
183
184	dealloc(f->f_devdata, sizeof(struct rz_softc));
185	f->f_devdata = (void *)0;
186	return (0);
187}
188#endif
189