FreeBSD/Linux Kernel Cross Reference
sys/dev/ofw/ofw_disk.c
1 /*-
2 * Copyright (C) 2002 Benno Rice <benno@FreeBSD.org>
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 *
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: src/sys/dev/ofw/ofw_disk.c,v 1.14.2.1 2005/01/30 00:59:56 imp Exp $");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/bio.h>
34 #include <sys/module.h>
35 #include <sys/bus.h>
36 #include <sys/conf.h>
37 #include <sys/kernel.h>
38 #include <sys/limits.h>
39 #include <geom/geom_disk.h>
40
41 #include <dev/ofw/openfirm.h>
42
43 #include <machine/bus.h>
44 #include <machine/md_var.h>
45 #include <machine/nexusvar.h>
46
47 #define OFWD_BLOCKSIZE 512
48
49 struct ofwd_softc
50 {
51 device_t ofwd_dev;
52 struct disk *ofwd_disk;
53 phandle_t ofwd_package;
54 ihandle_t ofwd_instance;
55 };
56
57 /*
58 * Disk device bus interface.
59 */
60 static void ofwd_identify(driver_t *, device_t);
61 static int ofwd_probe(device_t);
62 static int ofwd_attach(device_t);
63
64 static device_method_t ofwd_methods[] = {
65 DEVMETHOD(device_identify, ofwd_identify),
66 DEVMETHOD(device_probe, ofwd_probe),
67 DEVMETHOD(device_attach, ofwd_attach),
68 { 0, 0 }
69 };
70
71 static driver_t ofwd_driver = {
72 "ofwd",
73 ofwd_methods,
74 sizeof(struct ofwd_softc)
75 };
76
77 static devclass_t ofwd_devclass;
78
79 DRIVER_MODULE(ofwd, nexus, ofwd_driver, ofwd_devclass, 0, 0);
80
81 /*
82 * Disk device control interface.
83 */
84 static disk_strategy_t ofwd_strategy;
85
86 /*
87 * Handle an I/O request.
88 */
89 static void
90 ofwd_strategy(struct bio *bp)
91 {
92 struct ofwd_softc *sc;
93 long r;
94
95 sc = (struct ofwd_softc *)bp->bio_disk->d_drv1;
96
97 if (sc == NULL) {
98 printf("ofwd: bio for invalid disk!\n");
99 biofinish(bp, NULL, EINVAL);
100 return;
101 }
102
103 bp->bio_resid = bp->bio_bcount;
104
105 r = OF_seek(sc->ofwd_instance, bp->bio_offset);
106 if (r == -1) {
107 device_printf(sc->ofwd_dev, "seek failed\n");
108 biofinish(bp, NULL, EIO);
109 return;
110 }
111
112 if (bp->bio_cmd == BIO_READ) {
113 r = OF_read(sc->ofwd_instance, (void *)bp->bio_data,
114 bp->bio_bcount);
115 } else {
116 r = OF_write(sc->ofwd_instance, (void *)bp->bio_data,
117 bp->bio_bcount);
118 }
119
120 if (r > bp->bio_bcount)
121 panic("ofwd: more bytes read/written than requested");
122 if (r == -1) {
123 device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
124 r, bp->bio_bcount);
125 biofinish(bp, NULL, EIO);
126 return;
127 }
128
129 bp->bio_resid -= r;
130
131 if (r < bp->bio_bcount) {
132 device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
133 r, bp->bio_bcount);
134 biofinish(bp, NULL, EIO); /* XXX: probably not an error */
135 return;
136 }
137 biodone(bp);
138 return;
139 }
140
141 /*
142 * Attach the Open Firmware disk to nexus if present.
143 */
144 static void
145 ofwd_identify(driver_t *driver, device_t parent)
146 {
147 device_t child;
148 phandle_t ofd;
149 static char type[8];
150
151 ofd = OF_finddevice("ofwdisk");
152 if (ofd == -1)
153 return;
154
155 OF_getprop(ofd, "device_type", type, sizeof(type));
156
157 child = BUS_ADD_CHILD(parent, INT_MAX, "ofwd", 0);
158 if (child != NULL) {
159 nexus_set_device_type(child, type);
160 nexus_set_node(child, ofd);
161 }
162 }
163
164 /*
165 * Probe for an Open Firmware disk.
166 */
167 static int
168 ofwd_probe(device_t dev)
169 {
170 char *type;
171 char fname[32];
172 phandle_t node;
173
174 type = nexus_get_device_type(dev);
175 node = nexus_get_node(dev);
176
177 if (type == NULL ||
178 (strcmp(type, "disk") != 0 && strcmp(type, "block") != 0))
179 return (ENXIO);
180
181 if (OF_getprop(node, "file", fname, sizeof(fname)) == -1)
182 return (ENXIO);
183
184 device_set_desc(dev, "Open Firmware disk");
185 return (0);
186 }
187
188 static int
189 ofwd_attach(device_t dev)
190 {
191 struct ofwd_softc *sc;
192 char path[128];
193 char fname[32];
194
195 sc = device_get_softc(dev);
196 sc->ofwd_dev = dev;
197
198 bzero(path, 128);
199 OF_package_to_path(nexus_get_node(dev), path, 128);
200 OF_getprop(nexus_get_node(dev), "file", fname, sizeof(fname));
201 device_printf(dev, "located at %s, file %s\n", path, fname);
202 sc->ofwd_instance = OF_open(path);
203 if (sc->ofwd_instance == -1) {
204 device_printf(dev, "could not create instance\n");
205 return (ENXIO);
206 }
207
208 sc->ofwd_disk = disk_alloc();
209 sc->ofwd_disk->d_strategy = ofwd_strategy;
210 sc->ofwd_disk->d_name = "ofwd";
211 sc->ofwd_disk->d_sectorsize = OFWD_BLOCKSIZE;
212 sc->ofwd_disk->d_mediasize = (off_t)33554432 * OFWD_BLOCKSIZE;
213 sc->ofwd_disk->d_fwsectors = 0;
214 sc->ofwd_disk->d_fwheads = 0;
215 sc->ofwd_disk->d_drv1 = sc;
216 sc->ofwd_disk->d_maxsize = PAGE_SIZE;
217 sc->ofwd_disk->d_unit = device_get_unit(dev);
218 sc->ofwd_disk->d_flags = DISKFLAG_NEEDSGIANT;
219 disk_create(sc->ofwd_disk, DISK_VERSION);
220
221 return (0);
222 }
Cache object: 08ed00cb2d7cc29a29835dd30095f9ae
|