ofw_disk.c revision 84970
1/* 2 * Copyright (C) 2000 Benno Rice. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * $FreeBSD: head/sys/boot/ofw/libofw/ofw_disk.c 84970 2001-10-15 09:35:40Z robert $ 26 */ 27 28/* 29 * Disk I/O routines using Open Firmware 30 */ 31 32#include <sys/param.h> 33#include <sys/disklabel.h> 34 35#include <netinet/in.h> 36 37#include <machine/stdarg.h> 38 39#include <stand.h> 40 41#include "bootstrap.h" 42#include "libofw.h" 43 44#define DISKSECSZ 512 45#define DISKLABELSEC 0 46#define DISKLABELOFF 128 47 48static int ofwd_init(void); 49static int ofwd_strategy(void *devdata, int flag, daddr_t dblk, 50 size_t size, char *buf, size_t *rsize); 51static int ofwd_open(struct open_file *f, ...); 52static int ofwd_close(struct open_file *f); 53static void ofwd_print(int verbose); 54static char * ofwd_getdevpath(int unit); 55int readdisklabel(struct ofw_devdesc *); 56 57struct devsw ofwdisk = { 58 "disk", 59 DEVT_DISK, 60 ofwd_init, 61 ofwd_strategy, 62 ofwd_open, 63 ofwd_close, 64 noioctl, 65 ofwd_print 66}; 67 68static struct ofwdinfo { 69 int ofwd_unit; 70 char ofwd_path[255]; 71} ofwdinfo[MAXDEV]; 72static int nofwdinfo = 0; 73 74static int 75ofwd_init(void) 76{ 77 int ret; 78 char devpath[255]; 79 ihandle_t instance; 80 81 printf("ofwd_init: searching for block devices\n"); 82 ofw_devsearch_init(); 83 while ((ret = ofw_devsearch("block", devpath)) != 0) { 84 devpath[sizeof devpath - 1] = 0; 85 printf("ofwd_init: devpath=%s\n", devpath); 86 if (ret == -1) { 87 printf("ofwd_init: ret=%d\n", ret); 88 return (1); 89 } 90#ifdef DEBUG 91 printf("devpath=\"%s\" ret=%d\n", devpath, ret); 92#endif 93 94 if (strcmp(devpath, "/pci@1f,0/pci@1,1/ide@3/cdrom") == 0) 95 continue; 96 97 instance = OF_open(devpath); 98 if (instance != -1) { 99 ofwdinfo[nofwdinfo].ofwd_unit = nofwdinfo; 100 strncpy(ofwdinfo[nofwdinfo].ofwd_path, devpath, 255); 101 printf("disk%d is %s\n", nofwdinfo, ofwdinfo[nofwdinfo].ofwd_path); 102 nofwdinfo++; 103 OF_close(instance); 104 } 105 106 if (nofwdinfo > MAXDEV) { 107 printf("Hit MAXDEV probing disks.\n"); 108 return (1); 109 } 110 } 111 112 printf("ofwd_init: return (0)\n"); 113 return (0); 114} 115 116static int 117ofwd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, 118 size_t *rsize) 119{ 120 struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata; 121 unsigned long pos; 122 int n; 123 int i, j; 124 125 pos = (dp->d_kind.ofwdisk.partoff + dblk) * dp->d_kind.ofwdisk.bsize; 126 127 do { 128 if (OF_seek(dp->d_kind.ofwdisk.handle, pos) < 0) { 129 return EIO; 130 } 131 n = OF_read(dp->d_kind.ofwdisk.handle, buf, size); 132 if (n < 0 && n != -2) { 133 return EIO; 134 } 135 } while (n == -2); 136 137 *rsize = size; 138 return 0; 139} 140 141static int 142ofwd_open(struct open_file *f, ...) 143{ 144 va_list vl; 145 struct ofw_devdesc *dp; 146 char *devpath; 147 phandle_t diskh; 148 char buf[8192]; 149 int i, j; 150 151 va_start(vl, f); 152 dp = va_arg(vl, struct ofw_devdesc *); 153 va_end(vl); 154 155 devpath = ofwd_getdevpath(dp->d_kind.ofwdisk.unit); 156 if ((diskh = OF_open(devpath)) == -1) { 157 printf("ofwd_open: Could not open %s\n", devpath); 158 return 1; 159 } 160 dp->d_kind.ofwdisk.bsize = DISKSECSZ; 161 dp->d_kind.ofwdisk.handle = diskh; 162 readdisklabel(dp); 163 164 return 0; 165} 166 167/* XXX This is a NetBSD header! */ 168#include "disklabel.h" 169int 170readdisklabel(struct ofw_devdesc *dp) 171{ 172 char buf[DISKSECSZ]; 173 struct partition *p; 174 struct disklabel *lp; 175 size_t size; 176 int i; 177 178 dp->d_kind.ofwdisk.partoff = 0; 179 180 dp->d_dev->dv_strategy(dp, 0, DISKLABELSEC, sizeof(buf), buf, &size); 181 182 lp = (struct disklabel *)(buf + DISKLABELOFF); 183 p = lp->d_partitions; 184 for (i = 0; i < MAXPARTITIONS; i++) { 185 if (i == dp->d_kind.ofwdisk.partition) { 186 dp->d_kind.ofwdisk.partoff = p->p_offset; 187 return 0; 188 } 189 p++; 190 } 191 return 1; 192} 193 194static int 195ofwd_close(struct open_file *f) 196{ 197 struct ofw_devdesc *dev = f->f_devdata; 198 OF_close(dev->d_kind.ofwdisk.handle); 199 200 return 0; 201} 202 203static void 204ofwd_print(int verbose) 205{ 206 int i; 207 char line[80]; 208 209 for (i = 0; i < nofwdinfo; i++) { 210 sprintf(line, " disk%d: %s", i, ofwdinfo[i].ofwd_path); 211 pager_output(line); 212 pager_output("\n"); 213 } 214 return; 215} 216 217int 218ofwd_getunit(const char *path) 219{ 220 int i; 221 222 for (i = 0; i < nofwdinfo; i++) { 223 if (strcmp(path, ofwdinfo[i].ofwd_path) == 0) 224 return i; 225 } 226 227 return -1; 228} 229 230static char * 231ofwd_getdevpath(int unit) 232{ 233 int i; 234 235 for (i = 0; i < nofwdinfo; i++) { 236 if (ofwdinfo[i].ofwd_unit == unit) 237 return ofwdinfo[i].ofwd_path; 238 } 239 return 0; 240} 241