1139738Simp/*-
267204Sobrien * Copyright (C) 2000 Benno Rice.
367204Sobrien * All rights reserved.
467204Sobrien *
567204Sobrien * Redistribution and use in source and binary forms, with or without
667204Sobrien * modification, are permitted provided that the following conditions
767204Sobrien * are met:
867204Sobrien * 1. Redistributions of source code must retain the above copyright
967204Sobrien *    notice, this list of conditions and the following disclaimer.
1067204Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1167204Sobrien *    notice, this list of conditions and the following disclaimer in the
1267204Sobrien *    documentation and/or other materials provided with the distribution.
1367204Sobrien *
1467204Sobrien * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
1567204Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1667204Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1767204Sobrien * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1867204Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1967204Sobrien * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2067204Sobrien * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2167204Sobrien * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2267204Sobrien * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2367204Sobrien * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2467204Sobrien */
2567204Sobrien
26124140Sobrien#include <sys/cdefs.h>
27124140Sobrien__FBSDID("$FreeBSD$");
28124140Sobrien
2967204Sobrien/*
3067204Sobrien * Disk I/O routines using Open Firmware
3167204Sobrien */
3267204Sobrien
3367204Sobrien#include <sys/param.h>
3467204Sobrien
3567204Sobrien#include <netinet/in.h>
3667204Sobrien
3784970Srobert#include <machine/stdarg.h>
3884970Srobert
3967204Sobrien#include <stand.h>
4067204Sobrien
4167204Sobrien#include "bootstrap.h"
4267204Sobrien#include "libofw.h"
4367204Sobrien
4467204Sobrienstatic int	ofwd_init(void);
45237091Smariusstatic int	ofwd_strategy(void *devdata, int flag, daddr_t dblk,
46237091Smarius		    size_t size, char *buf, size_t *rsize);
4767204Sobrienstatic int	ofwd_open(struct open_file *f, ...);
4867204Sobrienstatic int	ofwd_close(struct open_file *f);
49106738Sjakestatic int	ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
5067204Sobrienstatic void	ofwd_print(int verbose);
5167204Sobrien
5267204Sobrienstruct devsw ofwdisk = {
53106738Sjake	"block",
5467204Sobrien	DEVT_DISK,
5567204Sobrien	ofwd_init,
5667204Sobrien	ofwd_strategy,
5767204Sobrien	ofwd_open,
5867204Sobrien	ofwd_close,
59106738Sjake	ofwd_ioctl,
6067204Sobrien	ofwd_print
6167204Sobrien};
6267204Sobrien
63237091Smarius/*
64237091Smarius * We're not guaranteed to be able to open a device more than once and there
65237091Smarius * is no OFW standard method to determine whether a device is already opened.
66237091Smarius * Opening a device multiple times simultaneously happens to work with most
67237091Smarius * OFW block device drivers but triggers a trap with at least the driver for
68237091Smarius * the on-board controllers of Sun Fire V100 and Ultra 1.  Upper layers and MI
69237091Smarius * code expect to be able to open a device more than once however.  Given that
70237091Smarius * different partitions of the same device might be opened at the same time as
71237091Smarius * done by ZFS, we can't generally just keep track of the opened devices and
72237091Smarius * reuse the instance handle when asked to open an already opened device.  So
73237091Smarius * the best we can do is to cache the lastly used device path and close and
74237091Smarius * open devices in ofwd_strategy() as needed.
75237091Smarius */
76237091Smariusstatic struct ofw_devdesc *kdp;
77151650Smarius
7867204Sobrienstatic int
7996423Sjakeofwd_init(void)
8096423Sjake{
81151650Smarius
82237091Smarius	return (0);
8396423Sjake}
8496423Sjake
8596423Sjakestatic int
86237091Smariusofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size,
87237091Smarius    char *buf, size_t *rsize)
8867204Sobrien{
8984970Srobert	struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
90123700Sgrehan	daddr_t pos;
9184970Srobert	int n;
9284970Srobert
93237091Smarius	if (dp != kdp) {
94237091Smarius		if (kdp != NULL) {
95237091Smarius#if !defined(__powerpc__)
96237091Smarius			OF_close(kdp->d_handle);
97237091Smarius#endif
98237091Smarius			kdp = NULL;
99237091Smarius		}
100237091Smarius		if ((dp->d_handle = OF_open(dp->d_path)) == -1)
101237091Smarius			return (ENOENT);
102237091Smarius		kdp = dp;
103237091Smarius	}
104237091Smarius
105106738Sjake	pos = dblk * 512;
10684970Srobert	do {
107106738Sjake		if (OF_seek(dp->d_handle, pos) < 0)
108237091Smarius			return (EIO);
109106738Sjake		n = OF_read(dp->d_handle, buf, size);
110106738Sjake		if (n < 0 && n != -2)
111237091Smarius			return (EIO);
11284970Srobert	} while (n == -2);
11384970Srobert	*rsize = size;
114237091Smarius	return (0);
11567204Sobrien}
11667204Sobrien
11767204Sobrienstatic int
11867204Sobrienofwd_open(struct open_file *f, ...)
11967204Sobrien{
120106738Sjake	struct ofw_devdesc *dp;
12184970Srobert	va_list vl;
12284970Srobert
12384970Srobert	va_start(vl, f);
12484970Srobert	dp = va_arg(vl, struct ofw_devdesc *);
12584970Srobert	va_end(vl);
126237091Smarius
127237091Smarius	if (dp != kdp) {
128237091Smarius		if (kdp != NULL) {
129237091Smarius			OF_close(kdp->d_handle);
130237091Smarius			kdp = NULL;
131151650Smarius		}
132237091Smarius		if ((dp->d_handle = OF_open(dp->d_path)) == -1) {
133237091Smarius			printf("%s: Could not open %s\n", __func__,
134237091Smarius			    dp->d_path);
135237091Smarius			return (ENOENT);
136237091Smarius		}
137237091Smarius		kdp = dp;
138151650Smarius	}
139237091Smarius	return (0);
14067204Sobrien}
14167204Sobrien
142106738Sjakestatic int
143106738Sjakeofwd_close(struct open_file *f)
14484970Srobert{
145106738Sjake	struct ofw_devdesc *dev = f->f_devdata;
14684970Srobert
147237091Smarius	if (dev == kdp) {
148237091Smarius#if !defined(__powerpc__)
149237091Smarius		OF_close(dev->d_handle);
150237091Smarius#endif
151237091Smarius		kdp = NULL;
152151650Smarius	}
153237091Smarius	return (0);
15484970Srobert}
15584970Srobert
15667204Sobrienstatic int
157237091Smariusofwd_ioctl(struct open_file *f __unused, u_long cmd __unused,
158237091Smarius    void *data __unused)
15967204Sobrien{
16084970Srobert
161106738Sjake	return (EINVAL);
16267204Sobrien}
16367204Sobrien
16467204Sobrienstatic void
165237091Smariusofwd_print(int verbose __unused)
16667204Sobrien{
167151650Smarius
16867204Sobrien}
169