ofw_disk.c revision 237091
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: stable/9/sys/boot/ofw/libofw/ofw_disk.c 237091 2012-06-14 19:55:19Z marius $"); 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