1/*	$NetBSD: disk.c,v 1.5 2011/02/20 07:52:43 matt 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 *	@(#)disk.c	8.1 (Berkeley) 6/10/93
35 */
36
37#include <lib/libsa/stand.h>
38
39#include <sys/param.h>
40#include <sys/disklabel.h>
41
42#include <dev/arcbios/arcbios.h>
43
44#include "common.h"
45#include "disk.h"
46
47#define	RF_PROTECTED_SECTORS	64	/* XXX refer to <.../rf_optnames.h> */
48
49struct	disk_softc {
50	u_long	sc_fd;			/* ARCBIOS file id */
51	int	sc_part;		/* disk partition number */
52	struct	disklabel sc_label;	/* disk label for this disk */
53};
54
55int
56diskstrategy(void *devdata, int rw, daddr_t bn, size_t reqcnt, void *addr,
57    size_t *cnt)
58{
59	struct disk_softc *sc = (struct disk_softc *)devdata;
60	int part = sc->sc_part;
61	struct partition *pp = &sc->sc_label.d_partitions[part];
62	long error;
63	int64_t offset;
64	u_long count;
65
66	offset = bn;
67
68	/*
69	 * Partial-block transfers not handled.
70	 */
71	if (reqcnt & (DEV_BSIZE - 1)) {
72		*cnt = 0;
73		return EINVAL;
74	}
75
76	offset += pp->p_offset;
77
78	if (pp->p_fstype == FS_RAID)
79		offset += RF_PROTECTED_SECTORS;
80
81	/*
82	 * Convert from blocks to bytes.
83	 */
84	offset *= DEV_BSIZE;
85
86	error = arcbios_Seek(sc->sc_fd, &offset, 0);
87	if (error != ARCBIOS_ESUCCESS)
88		return EIO;
89	error = arcbios_Read(sc->sc_fd, addr, reqcnt, &count);
90	if (error != ARCBIOS_ESUCCESS)
91		return EIO;
92
93	*cnt = count;
94	return 0;
95}
96
97int
98diskopen(struct open_file *f, ...)
99{
100	int part;
101
102	struct disk_softc *sc;
103	struct disklabel *lp;
104#ifdef arc
105	char *msg, buf[DEV_BSIZE];
106	size_t cnt;
107	int mbrp_off, i;
108#endif
109	int error;
110	u_long fd;
111	char *device;
112	va_list ap;
113
114	va_start(ap, f);
115
116	device = va_arg(ap, char *);
117
118	/*
119	 * For NetBSD/sgimips, since we use the SGI partition map directly,
120	 * we fake an in-core NetBSD disklabel with offset of 0.
121	 *
122	 * For NetBSD/arc, there is a MBR partition map on the disk, which we
123	 * then expect to find a NetBSD disklabel within the MBR partition.
124	 * We require that the kernel be located in first partition in the
125	 * NetBSD disklabel, because we have not other way to represent the
126	 * root partition.
127	 */
128	part = 0;
129
130	if (part >= MAXPARTITIONS)
131		return ENXIO;
132
133	error = arcbios_Open(device, 0, &fd);
134	if (error) {
135		printf("diskopen: open failed, errno = %d\n", error);
136		return ENXIO;
137	}
138
139	sc = alloc(sizeof(struct disk_softc));
140	memset(sc, 0, sizeof(struct disk_softc));
141	f->f_devdata = (void *)sc;
142
143	sc->sc_fd = fd;
144	sc->sc_part = part;
145
146	/* try to read disk label and partition table information */
147	lp = &sc->sc_label;
148	lp->d_secsize = DEV_BSIZE;
149	lp->d_secpercyl = 1;
150	lp->d_npartitions = MAXPARTITIONS;
151	lp->d_partitions[part].p_offset = 0;
152	lp->d_partitions[part].p_size = 0x7fffffff;
153
154#ifdef arc
155	error = diskstrategy(sc, F_READ, (daddr_t)LABELSECTOR, DEV_BSIZE,
156	    buf, &cnt);
157	if (error || cnt != DEV_BSIZE) {
158		printf("%s: can't read disklabel, errno = %d\n",
159		    device, error);
160		dealloc(sc, sizeof(struct disk_softc));
161		return ENXIO;
162	}
163	msg = getdisklabel(buf, lp);
164	if (msg) {
165		/* If no label, just assume 0 and return */
166		return 0;
167	}
168
169	/*
170	 * On arc, we can't open whole disk, but can open each partition with
171	 * OSLOADPARTITION like scsi(0)disk(0)rdisk()partition(1) etc.
172	 * Thus, we don't have to add offset of the MBR partition.
173	 */
174	/* XXX magic: partition 2 is whole NetBSD partition */
175	mbrp_off = lp->d_partitions[2].p_offset;
176	for (i = 0; i < MAXPARTITIONS; i++) {
177		if (lp->d_partitions[i].p_fstype != FS_UNUSED &&
178		    lp->d_partitions[i].p_offset >= mbrp_off)
179			lp->d_partitions[i].p_offset -= mbrp_off;
180	}
181
182	if (part >= lp->d_npartitions ||
183	    lp->d_partitions[part].p_fstype == FS_UNUSED ||
184	    lp->d_partitions[part].p_size == 0) {
185		dealloc(sc, sizeof(struct disk_softc));
186		return ENXIO;
187	}
188#endif
189	return 0;
190}
191
192#ifndef LIBSA_NO_DEV_CLOSE
193int
194diskclose(struct open_file *f)
195{
196
197	arcbios_Close(((struct disk_softc *)(f->f_devdata))->sc_fd);
198	dealloc(f->f_devdata, sizeof(struct disk_softc));
199	f->f_devdata = NULL;
200	return 0;
201}
202#endif
203