mscp_disk.c revision 1.56.10.2 1 1.56.10.2 ad /* $NetBSD: mscp_disk.c,v 1.56.10.2 2007/07/29 12:15:44 ad Exp $ */
2 1.56.10.2 ad /*
3 1.56.10.2 ad * Copyright (c) 1988 Regents of the University of California.
4 1.56.10.2 ad * All rights reserved.
5 1.56.10.2 ad *
6 1.56.10.2 ad * This code is derived from software contributed to Berkeley by
7 1.56.10.2 ad * Chris Torek.
8 1.56.10.2 ad *
9 1.56.10.2 ad * Redistribution and use in source and binary forms, with or without
10 1.56.10.2 ad * modification, are permitted provided that the following conditions
11 1.56.10.2 ad * are met:
12 1.56.10.2 ad * 1. Redistributions of source code must retain the above copyright
13 1.56.10.2 ad * notice, this list of conditions and the following disclaimer.
14 1.56.10.2 ad * 2. Redistributions in binary form must reproduce the above copyright
15 1.56.10.2 ad * notice, this list of conditions and the following disclaimer in the
16 1.56.10.2 ad * documentation and/or other materials provided with the distribution.
17 1.56.10.2 ad * 3. Neither the name of the University nor the names of its contributors
18 1.56.10.2 ad * may be used to endorse or promote products derived from this software
19 1.56.10.2 ad * without specific prior written permission.
20 1.56.10.2 ad *
21 1.56.10.2 ad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 1.56.10.2 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 1.56.10.2 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.56.10.2 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 1.56.10.2 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.56.10.2 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.56.10.2 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.56.10.2 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.56.10.2 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.56.10.2 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.56.10.2 ad * SUCH DAMAGE.
32 1.56.10.2 ad *
33 1.56.10.2 ad * @(#)uda.c 7.32 (Berkeley) 2/13/91
34 1.56.10.2 ad */
35 1.56.10.2 ad
36 1.56.10.2 ad /*
37 1.56.10.2 ad * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
38 1.56.10.2 ad *
39 1.56.10.2 ad * This code is derived from software contributed to Berkeley by
40 1.56.10.2 ad * Chris Torek.
41 1.56.10.2 ad *
42 1.56.10.2 ad * Redistribution and use in source and binary forms, with or without
43 1.56.10.2 ad * modification, are permitted provided that the following conditions
44 1.56.10.2 ad * are met:
45 1.56.10.2 ad * 1. Redistributions of source code must retain the above copyright
46 1.56.10.2 ad * notice, this list of conditions and the following disclaimer.
47 1.56.10.2 ad * 2. Redistributions in binary form must reproduce the above copyright
48 1.56.10.2 ad * notice, this list of conditions and the following disclaimer in the
49 1.56.10.2 ad * documentation and/or other materials provided with the distribution.
50 1.56.10.2 ad * 3. All advertising materials mentioning features or use of this software
51 1.56.10.2 ad * must display the following acknowledgement:
52 1.56.10.2 ad * This product includes software developed by the University of
53 1.56.10.2 ad * California, Berkeley and its contributors.
54 1.56.10.2 ad * 4. Neither the name of the University nor the names of its contributors
55 1.56.10.2 ad * may be used to endorse or promote products derived from this software
56 1.56.10.2 ad * without specific prior written permission.
57 1.56.10.2 ad *
58 1.56.10.2 ad * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.56.10.2 ad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.56.10.2 ad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.56.10.2 ad * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.56.10.2 ad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.56.10.2 ad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.56.10.2 ad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.56.10.2 ad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.56.10.2 ad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.56.10.2 ad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.56.10.2 ad * SUCH DAMAGE.
69 1.56.10.2 ad *
70 1.56.10.2 ad * @(#)uda.c 7.32 (Berkeley) 2/13/91
71 1.56.10.2 ad */
72 1.56.10.2 ad
73 1.56.10.2 ad /*
74 1.56.10.2 ad * RA disk device driver
75 1.56.10.2 ad * RX MSCP floppy disk device driver
76 1.56.10.2 ad */
77 1.56.10.2 ad
78 1.56.10.2 ad /*
79 1.56.10.2 ad * TODO
80 1.56.10.2 ad * write bad block forwarding code
81 1.56.10.2 ad */
82 1.56.10.2 ad
83 1.56.10.2 ad #include <sys/cdefs.h>
84 1.56.10.2 ad __KERNEL_RCSID(0, "$NetBSD: mscp_disk.c,v 1.56.10.2 2007/07/29 12:15:44 ad Exp $");
85 1.56.10.2 ad
86 1.56.10.2 ad #include <sys/param.h>
87 1.56.10.2 ad #include <sys/buf.h>
88 1.56.10.2 ad #include <sys/bufq.h>
89 1.56.10.2 ad #include <sys/device.h>
90 1.56.10.2 ad #include <sys/disk.h>
91 1.56.10.2 ad #include <sys/disklabel.h>
92 1.56.10.2 ad #include <sys/ioctl.h>
93 1.56.10.2 ad #include <sys/stat.h>
94 1.56.10.2 ad #include <sys/fcntl.h>
95 1.56.10.2 ad #include <sys/reboot.h>
96 1.56.10.2 ad #include <sys/proc.h>
97 1.56.10.2 ad #include <sys/systm.h>
98 1.56.10.2 ad #include <sys/conf.h>
99 1.56.10.2 ad
100 1.56.10.2 ad #include <ufs/ufs/dinode.h>
101 1.56.10.2 ad #include <ufs/ffs/fs.h>
102 1.56.10.2 ad
103 1.56.10.2 ad #include <machine/bus.h>
104 1.56.10.2 ad #include <machine/cpu.h>
105 1.56.10.2 ad
106 1.56.10.2 ad #include <dev/mscp/mscp.h>
107 1.56.10.2 ad #include <dev/mscp/mscpreg.h>
108 1.56.10.2 ad #include <dev/mscp/mscpvar.h>
109 1.56.10.2 ad
110 1.56.10.2 ad #include "locators.h"
111 1.56.10.2 ad #include "ioconf.h"
112 1.56.10.2 ad #include "ra.h"
113 1.56.10.2 ad
114 1.56.10.2 ad /*
115 1.56.10.2 ad * Drive status, per drive
116 1.56.10.2 ad */
117 1.56.10.2 ad struct ra_softc {
118 1.56.10.2 ad struct device ra_dev; /* Autoconf struct */
119 1.56.10.2 ad struct disk ra_disk;
120 1.56.10.2 ad int ra_state; /* open/closed state */
121 1.56.10.2 ad u_long ra_mediaid; /* media id */
122 1.56.10.2 ad int ra_hwunit; /* Hardware unit number */
123 1.56.10.2 ad int ra_havelabel; /* true if we have a label */
124 1.56.10.2 ad int ra_wlabel; /* label sector is currently writable */
125 1.56.10.2 ad };
126 1.56.10.2 ad
127 1.56.10.2 ad #define rx_softc ra_softc
128 1.56.10.2 ad
129 1.56.10.2 ad void rxattach(struct device *, struct device *, void *);
130 1.56.10.2 ad int rx_putonline(struct rx_softc *);
131 1.56.10.2 ad void rrmakelabel(struct disklabel *, long);
132 1.56.10.2 ad
133 1.56.10.2 ad #if NRA
134 1.56.10.2 ad
135 1.56.10.2 ad int ramatch(struct device *, struct cfdata *, void *);
136 1.56.10.2 ad void raattach(struct device *, struct device *, void *);
137 1.56.10.2 ad int ra_putonline(struct ra_softc *);
138 1.56.10.2 ad
139 1.56.10.2 ad CFATTACH_DECL(ra, sizeof(struct ra_softc),
140 1.56.10.2 ad ramatch, rxattach, NULL, NULL);
141 1.56.10.2 ad
142 1.56.10.2 ad dev_type_open(raopen);
143 1.56.10.2 ad dev_type_close(raclose);
144 1.56.10.2 ad dev_type_read(raread);
145 1.56.10.2 ad dev_type_write(rawrite);
146 1.56.10.2 ad dev_type_ioctl(raioctl);
147 1.56.10.2 ad dev_type_strategy(rastrategy);
148 1.56.10.2 ad dev_type_dump(radump);
149 1.56.10.2 ad dev_type_size(rasize);
150 1.56.10.2 ad
151 1.56.10.2 ad const struct bdevsw ra_bdevsw = {
152 1.56.10.2 ad raopen, raclose, rastrategy, raioctl, radump, rasize, D_DISK
153 1.56.10.2 ad };
154 1.56.10.2 ad
155 1.56.10.2 ad const struct cdevsw ra_cdevsw = {
156 1.56.10.2 ad raopen, raclose, raread, rawrite, raioctl,
157 1.56.10.2 ad nostop, notty, nopoll, nommap, nokqfilter, D_DISK
158 1.56.10.2 ad };
159 1.56.10.2 ad
160 1.56.10.2 ad static struct dkdriver radkdriver = {
161 1.56.10.2 ad rastrategy, minphys
162 1.56.10.2 ad };
163 1.56.10.2 ad
164 1.56.10.2 ad /*
165 1.56.10.2 ad * More driver definitions, for generic MSCP code.
166 1.56.10.2 ad */
167 1.56.10.2 ad
168 1.56.10.2 ad int
169 1.56.10.2 ad ramatch(parent, cf, aux)
170 1.56.10.2 ad struct device *parent;
171 1.56.10.2 ad struct cfdata *cf;
172 1.56.10.2 ad void *aux;
173 1.56.10.2 ad {
174 1.56.10.2 ad struct drive_attach_args *da = aux;
175 1.56.10.2 ad struct mscp *mp = da->da_mp;
176 1.56.10.2 ad
177 1.56.10.2 ad if ((da->da_typ & MSCPBUS_DISK) == 0)
178 1.56.10.2 ad return 0;
179 1.56.10.2 ad if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
180 1.56.10.2 ad cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
181 1.56.10.2 ad return 0;
182 1.56.10.2 ad /*
183 1.56.10.2 ad * Check if this disk is a floppy; then don't configure it.
184 1.56.10.2 ad * Seems to be a safe way to test it per Chris Torek.
185 1.56.10.2 ad */
186 1.56.10.2 ad if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
187 1.56.10.2 ad return 0;
188 1.56.10.2 ad return 1;
189 1.56.10.2 ad }
190 1.56.10.2 ad
191 1.56.10.2 ad /*
192 1.56.10.2 ad * (Try to) put the drive online. This is done the first time the
193 1.56.10.2 ad * drive is opened, or if it har fallen offline.
194 1.56.10.2 ad */
195 1.56.10.2 ad int
196 1.56.10.2 ad ra_putonline(ra)
197 1.56.10.2 ad struct ra_softc *ra;
198 1.56.10.2 ad {
199 1.56.10.2 ad struct disklabel *dl;
200 1.56.10.2 ad const char *msg;
201 1.56.10.2 ad int maj;
202 1.56.10.2 ad
203 1.56.10.2 ad if (rx_putonline(ra) != MSCP_DONE)
204 1.56.10.2 ad return MSCP_FAILED;
205 1.56.10.2 ad
206 1.56.10.2 ad dl = ra->ra_disk.dk_label;
207 1.56.10.2 ad
208 1.56.10.2 ad ra->ra_state = DK_RDLABEL;
209 1.56.10.2 ad printf("%s", ra->ra_dev.dv_xname);
210 1.56.10.2 ad maj = cdevsw_lookup_major(&ra_cdevsw);
211 1.56.10.2 ad if ((msg = readdisklabel(MAKEDISKDEV(maj, device_unit(&ra->ra_dev),
212 1.56.10.2 ad RAW_PART), rastrategy, dl, NULL)) != NULL)
213 1.56.10.2 ad printf(": %s", msg);
214 1.56.10.2 ad else {
215 1.56.10.2 ad ra->ra_havelabel = 1;
216 1.56.10.2 ad ra->ra_state = DK_OPEN;
217 1.56.10.2 ad }
218 1.56.10.2 ad
219 1.56.10.2 ad printf(": size %d sectors\n", dl->d_secperunit);
220 1.56.10.2 ad
221 1.56.10.2 ad return MSCP_DONE;
222 1.56.10.2 ad }
223 1.56.10.2 ad
224 1.56.10.2 ad /*
225 1.56.10.2 ad * Open a drive.
226 1.56.10.2 ad */
227 1.56.10.2 ad /*ARGSUSED*/
228 1.56.10.2 ad int
229 1.56.10.2 ad raopen(dev, flag, fmt, l)
230 1.56.10.2 ad dev_t dev;
231 1.56.10.2 ad int flag, fmt;
232 1.56.10.2 ad struct lwp *l;
233 1.56.10.2 ad {
234 1.56.10.2 ad struct ra_softc *ra;
235 1.56.10.2 ad int error, part, unit, mask;
236 1.56.10.2 ad /*
237 1.56.10.2 ad * Make sure this is a reasonable open request.
238 1.56.10.2 ad */
239 1.56.10.2 ad unit = DISKUNIT(dev);
240 1.56.10.2 ad if (unit >= ra_cd.cd_ndevs)
241 1.56.10.2 ad return ENXIO;
242 1.56.10.2 ad ra = ra_cd.cd_devs[unit];
243 1.56.10.2 ad if (ra == 0)
244 1.56.10.2 ad return ENXIO;
245 1.56.10.2 ad
246 1.56.10.2 ad part = DISKPART(dev);
247 1.56.10.2 ad
248 1.56.10.2 ad mutex_enter(&ra->ra_disk.dk_openlock);
249 1.56.10.2 ad
250 1.56.10.2 ad /*
251 1.56.10.2 ad * If there are wedges, and this is not RAW_PART, then we
252 1.56.10.2 ad * need to fail.
253 1.56.10.2 ad */
254 1.56.10.2 ad if (ra->ra_disk.dk_nwedges != 0 && part != RAW_PART) {
255 1.56.10.2 ad error = EBUSY;
256 1.56.10.2 ad goto bad1;
257 1.56.10.2 ad }
258 1.56.10.2 ad
259 1.56.10.2 ad /*
260 1.56.10.2 ad * If this is the first open; we must first try to put
261 1.56.10.2 ad * the disk online (and read the label).
262 1.56.10.2 ad */
263 1.56.10.2 ad if (ra->ra_state == DK_CLOSED) {
264 1.56.10.2 ad if (ra_putonline(ra) == MSCP_FAILED) {
265 1.56.10.2 ad error = ENXIO;
266 1.56.10.2 ad goto bad1;
267 1.56.10.2 ad }
268 1.56.10.2 ad }
269 1.56.10.2 ad
270 1.56.10.2 ad /* If the disk has no label; allow writing everywhere */
271 1.56.10.2 ad if (ra->ra_havelabel == 0)
272 1.56.10.2 ad ra->ra_wlabel = 1;
273 1.56.10.2 ad
274 1.56.10.2 ad if (part >= ra->ra_disk.dk_label->d_npartitions) {
275 1.56.10.2 ad error = ENXIO;
276 1.56.10.2 ad goto bad1;
277 1.56.10.2 ad }
278 1.56.10.2 ad
279 1.56.10.2 ad /*
280 1.56.10.2 ad * Wait for the state to settle
281 1.56.10.2 ad */
282 1.56.10.2 ad #if notyet
283 1.56.10.2 ad while (ra->ra_state != DK_OPEN)
284 1.56.10.2 ad if ((error = tsleep((void *)ra, (PZERO + 1) | PCATCH,
285 1.56.10.2 ad devopn, 0))) {
286 1.56.10.2 ad splx(s);
287 1.56.10.2 ad return (error);
288 1.56.10.2 ad }
289 1.56.10.2 ad #endif
290 1.56.10.2 ad
291 1.56.10.2 ad mask = 1 << part;
292 1.56.10.2 ad
293 1.56.10.2 ad switch (fmt) {
294 1.56.10.2 ad case S_IFCHR:
295 1.56.10.2 ad ra->ra_disk.dk_copenmask |= mask;
296 1.56.10.2 ad break;
297 1.56.10.2 ad case S_IFBLK:
298 1.56.10.2 ad ra->ra_disk.dk_bopenmask |= mask;
299 1.56.10.2 ad break;
300 1.56.10.2 ad }
301 1.56.10.2 ad ra->ra_disk.dk_openmask |= mask;
302 1.56.10.2 ad error = 0;
303 1.56.10.2 ad bad1:
304 1.56.10.2 ad mutex_exit(&ra->ra_disk.dk_openlock);
305 1.56.10.2 ad return (error);
306 1.56.10.2 ad }
307 1.56.10.2 ad
308 1.56.10.2 ad /* ARGSUSED */
309 1.56.10.2 ad int
310 1.56.10.2 ad raclose(dev, flags, fmt, l)
311 1.56.10.2 ad dev_t dev;
312 1.56.10.2 ad int flags, fmt;
313 1.56.10.2 ad struct lwp *l;
314 1.56.10.2 ad {
315 1.56.10.2 ad int unit = DISKUNIT(dev);
316 1.56.10.2 ad struct ra_softc *ra = ra_cd.cd_devs[unit];
317 1.56.10.2 ad int mask = (1 << DISKPART(dev));
318 1.56.10.2 ad
319 1.56.10.2 ad mutex_enter(&ra->ra_disk.dk_openlock);
320 1.56.10.2 ad
321 1.56.10.2 ad switch (fmt) {
322 1.56.10.2 ad case S_IFCHR:
323 1.56.10.2 ad ra->ra_disk.dk_copenmask &= ~mask;
324 1.56.10.2 ad break;
325 1.56.10.2 ad case S_IFBLK:
326 1.56.10.2 ad ra->ra_disk.dk_bopenmask &= ~mask;
327 1.56.10.2 ad break;
328 1.56.10.2 ad }
329 1.56.10.2 ad ra->ra_disk.dk_openmask =
330 1.56.10.2 ad ra->ra_disk.dk_copenmask | ra->ra_disk.dk_bopenmask;
331 1.56.10.2 ad
332 1.56.10.2 ad /*
333 1.56.10.2 ad * Should wait for I/O to complete on this partition even if
334 1.56.10.2 ad * others are open, but wait for work on blkflush().
335 1.56.10.2 ad */
336 1.56.10.2 ad #if notyet
337 1.56.10.2 ad if (ra->ra_openpart == 0) {
338 1.56.10.2 ad s = spluba();
339 1.56.10.2 ad while (BUFQ_PEEK(udautab[unit]) != NULL)
340 1.56.10.2 ad (void) tsleep(&udautab[unit], PZERO - 1,
341 1.56.10.2 ad "raclose", 0);
342 1.56.10.2 ad splx(s);
343 1.56.10.2 ad ra->ra_state = CLOSED;
344 1.56.10.2 ad ra->ra_wlabel = 0;
345 1.56.10.2 ad }
346 1.56.10.2 ad #endif
347 1.56.10.2 ad mutex_exit(&ra->ra_disk.dk_openlock);
348 1.56.10.2 ad return (0);
349 1.56.10.2 ad }
350 1.56.10.2 ad
351 1.56.10.2 ad /*
352 1.56.10.2 ad * Queue a transfer request, and if possible, hand it to the controller.
353 1.56.10.2 ad */
354 1.56.10.2 ad void
355 1.56.10.2 ad rastrategy(bp)
356 1.56.10.2 ad struct buf *bp;
357 1.56.10.2 ad {
358 1.56.10.2 ad int unit;
359 1.56.10.2 ad struct ra_softc *ra;
360 1.56.10.2 ad int b;
361 1.56.10.2 ad
362 1.56.10.2 ad /*
363 1.56.10.2 ad * Make sure this is a reasonable drive to use.
364 1.56.10.2 ad */
365 1.56.10.2 ad unit = DISKUNIT(bp->b_dev);
366 1.56.10.2 ad if (unit > ra_cd.cd_ndevs || (ra = ra_cd.cd_devs[unit]) == NULL) {
367 1.56.10.2 ad bp->b_error = ENXIO;
368 1.56.10.2 ad goto done;
369 1.56.10.2 ad }
370 1.56.10.2 ad /*
371 1.56.10.2 ad * If drive is open `raw' or reading label, let it at it.
372 1.56.10.2 ad */
373 1.56.10.2 ad if (ra->ra_state == DK_RDLABEL) {
374 1.56.10.2 ad /* Make some statistics... /bqt */
375 1.56.10.2 ad b = splbio();
376 1.56.10.2 ad disk_busy(&ra->ra_disk);
377 1.56.10.2 ad splx(b);
378 1.56.10.2 ad mscp_strategy(bp, device_parent(&ra->ra_dev));
379 1.56.10.2 ad return;
380 1.56.10.2 ad }
381 1.56.10.2 ad
382 1.56.10.2 ad /* If disk is not online, try to put it online */
383 1.56.10.2 ad if (ra->ra_state == DK_CLOSED)
384 1.56.10.2 ad if (ra_putonline(ra) == MSCP_FAILED) {
385 1.56.10.2 ad bp->b_error = EIO;
386 1.56.10.2 ad goto done;
387 1.56.10.2 ad }
388 1.56.10.2 ad
389 1.56.10.2 ad /*
390 1.56.10.2 ad * Determine the size of the transfer, and make sure it is
391 1.56.10.2 ad * within the boundaries of the partition.
392 1.56.10.2 ad */
393 1.56.10.2 ad if (bounds_check_with_label(&ra->ra_disk, bp, ra->ra_wlabel) <= 0)
394 1.56.10.2 ad goto done;
395 1.56.10.2 ad
396 1.56.10.2 ad /* Make some statistics... /bqt */
397 1.56.10.2 ad b = splbio();
398 1.56.10.2 ad disk_busy(&ra->ra_disk);
399 1.56.10.2 ad splx(b);
400 1.56.10.2 ad mscp_strategy(bp, device_parent(&ra->ra_dev));
401 1.56.10.2 ad return;
402 1.56.10.2 ad
403 1.56.10.2 ad done:
404 1.56.10.2 ad biodone(bp);
405 1.56.10.2 ad }
406 1.56.10.2 ad
407 1.56.10.2 ad int
408 1.56.10.2 ad raread(dev, uio, flags)
409 1.56.10.2 ad dev_t dev;
410 1.56.10.2 ad struct uio *uio;
411 1.56.10.2 ad int flags;
412 1.56.10.2 ad {
413 1.56.10.2 ad
414 1.56.10.2 ad return (physio(rastrategy, NULL, dev, B_READ, minphys, uio));
415 1.56.10.2 ad }
416 1.56.10.2 ad
417 1.56.10.2 ad int
418 1.56.10.2 ad rawrite(dev, uio, flags)
419 1.56.10.2 ad dev_t dev;
420 1.56.10.2 ad struct uio *uio;
421 1.56.10.2 ad int flags;
422 1.56.10.2 ad {
423 1.56.10.2 ad
424 1.56.10.2 ad return (physio(rastrategy, NULL, dev, B_WRITE, minphys, uio));
425 1.56.10.2 ad }
426 1.56.10.2 ad
427 1.56.10.2 ad /*
428 1.56.10.2 ad * I/O controls.
429 1.56.10.2 ad */
430 1.56.10.2 ad int
431 1.56.10.2 ad raioctl(dev, cmd, data, flag, l)
432 1.56.10.2 ad dev_t dev;
433 1.56.10.2 ad u_long cmd;
434 1.56.10.2 ad void *data;
435 1.56.10.2 ad int flag;
436 1.56.10.2 ad struct lwp *l;
437 1.56.10.2 ad {
438 1.56.10.2 ad int unit = DISKUNIT(dev);
439 1.56.10.2 ad struct disklabel *lp, *tp;
440 1.56.10.2 ad struct ra_softc *ra = ra_cd.cd_devs[unit];
441 1.56.10.2 ad int error = 0;
442 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
443 1.56.10.2 ad struct disklabel newlabel;
444 1.56.10.2 ad #endif
445 1.56.10.2 ad
446 1.56.10.2 ad lp = ra->ra_disk.dk_label;
447 1.56.10.2 ad
448 1.56.10.2 ad switch (cmd) {
449 1.56.10.2 ad
450 1.56.10.2 ad case DIOCGDINFO:
451 1.56.10.2 ad bcopy(lp, data, sizeof (struct disklabel));
452 1.56.10.2 ad break;
453 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
454 1.56.10.2 ad case ODIOCGDINFO:
455 1.56.10.2 ad bcopy(lp, &newlabel, sizeof disklabel);
456 1.56.10.2 ad if (newlabel.d_npartitions > OLDMAXPARTITIONS)
457 1.56.10.2 ad return ENOTTY;
458 1.56.10.2 ad bcopy(&newlabel, data, sizeof (struct olddisklabel));
459 1.56.10.2 ad break;
460 1.56.10.2 ad #endif
461 1.56.10.2 ad
462 1.56.10.2 ad case DIOCGPART:
463 1.56.10.2 ad ((struct partinfo *)data)->disklab = lp;
464 1.56.10.2 ad ((struct partinfo *)data)->part =
465 1.56.10.2 ad &lp->d_partitions[DISKPART(dev)];
466 1.56.10.2 ad break;
467 1.56.10.2 ad
468 1.56.10.2 ad case DIOCWDINFO:
469 1.56.10.2 ad case DIOCSDINFO:
470 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
471 1.56.10.2 ad case ODIOCWDINFO:
472 1.56.10.2 ad case ODIOCSDINFO:
473 1.56.10.2 ad if (cmd == ODIOCSDINFO || xfer == ODIOCWDINFO) {
474 1.56.10.2 ad memset(&newlabel, 0, sizeof newlabel);
475 1.56.10.2 ad memcpy(&newlabel, data, sizeof (struct olddisklabel));
476 1.56.10.2 ad tp = &newlabel;
477 1.56.10.2 ad } else
478 1.56.10.2 ad #endif
479 1.56.10.2 ad tp = (struct disklabel *)data;
480 1.56.10.2 ad
481 1.56.10.2 ad if ((flag & FWRITE) == 0)
482 1.56.10.2 ad error = EBADF;
483 1.56.10.2 ad else {
484 1.56.10.2 ad mutex_enter(&ra->ra_disk.dk_openlock);
485 1.56.10.2 ad error = setdisklabel(lp, tp, 0, 0);
486 1.56.10.2 ad if ((error == 0) && (cmd == DIOCWDINFO
487 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
488 1.56.10.2 ad || cmd == ODIOCWDINFO
489 1.56.10.2 ad #else
490 1.56.10.2 ad )) {
491 1.56.10.2 ad #endif
492 1.56.10.2 ad ra->ra_wlabel = 1;
493 1.56.10.2 ad error = writedisklabel(dev, rastrategy, lp,0);
494 1.56.10.2 ad ra->ra_wlabel = 0;
495 1.56.10.2 ad }
496 1.56.10.2 ad mutex_exit(&ra->ra_disk.dk_openlock);
497 1.56.10.2 ad }
498 1.56.10.2 ad break;
499 1.56.10.2 ad
500 1.56.10.2 ad case DIOCWLABEL:
501 1.56.10.2 ad if ((flag & FWRITE) == 0)
502 1.56.10.2 ad error = EBADF;
503 1.56.10.2 ad else
504 1.56.10.2 ad ra->ra_wlabel = 1;
505 1.56.10.2 ad break;
506 1.56.10.2 ad
507 1.56.10.2 ad case DIOCGDEFLABEL:
508 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
509 1.56.10.2 ad case ODIOCGDEFLABEL:
510 1.56.10.2 ad if (cmd == ODIOCGDEFLABEL)
511 1.56.10.2 ad tp = &newlabel;
512 1.56.10.2 ad else
513 1.56.10.2 ad #else
514 1.56.10.2 ad tp = (struct disklabel *)data;
515 1.56.10.2 ad #endif
516 1.56.10.2 ad bzero(tp, sizeof(struct disklabel));
517 1.56.10.2 ad tp->d_secsize = lp->d_secsize;
518 1.56.10.2 ad tp->d_nsectors = lp->d_nsectors;
519 1.56.10.2 ad tp->d_ntracks = lp->d_ntracks;
520 1.56.10.2 ad tp->d_ncylinders = lp->d_ncylinders;
521 1.56.10.2 ad tp->d_secpercyl = lp->d_secpercyl;
522 1.56.10.2 ad tp->d_secperunit = lp->d_secperunit;
523 1.56.10.2 ad tp->d_type = DTYPE_MSCP;
524 1.56.10.2 ad tp->d_rpm = 3600;
525 1.56.10.2 ad rrmakelabel(tp, ra->ra_mediaid);
526 1.56.10.2 ad #ifdef __HAVE_OLD_DISKLABEL
527 1.56.10.2 ad if (cmd == ODIOCGDEFLABEL) {
528 1.56.10.2 ad if (tp->d_npartitions > OLDMAXPARTITIONS)
529 1.56.10.2 ad return ENOTTY;
530 1.56.10.2 ad memcpy(data, tp, sizeof (struct olddisklabel));
531 1.56.10.2 ad }
532 1.56.10.2 ad #endif
533 1.56.10.2 ad break;
534 1.56.10.2 ad
535 1.56.10.2 ad case DIOCAWEDGE:
536 1.56.10.2 ad {
537 1.56.10.2 ad struct dkwedge_info *dkw = (void *) data;
538 1.56.10.2 ad
539 1.56.10.2 ad if ((flag & FWRITE) == 0)
540 1.56.10.2 ad return (EBADF);
541 1.56.10.2 ad
542 1.56.10.2 ad /* If the ioctl happens here, the parent is us. */
543 1.56.10.2 ad strcpy(dkw->dkw_parent, ra->ra_dev.dv_xname);
544 1.56.10.2 ad return (dkwedge_add(dkw));
545 1.56.10.2 ad }
546 1.56.10.2 ad
547 1.56.10.2 ad case DIOCDWEDGE:
548 1.56.10.2 ad {
549 1.56.10.2 ad struct dkwedge_info *dkw = (void *) data;
550 1.56.10.2 ad
551 1.56.10.2 ad if ((flag & FWRITE) == 0)
552 1.56.10.2 ad return (EBADF);
553 1.56.10.2 ad
554 1.56.10.2 ad /* If the ioctl happens here, the parent is us. */
555 1.56.10.2 ad strcpy(dkw->dkw_parent, ra->ra_dev.dv_xname);
556 1.56.10.2 ad return (dkwedge_del(dkw));
557 1.56.10.2 ad }
558 1.56.10.2 ad
559 1.56.10.2 ad case DIOCLWEDGES:
560 1.56.10.2 ad {
561 1.56.10.2 ad struct dkwedge_list *dkwl = (void *) data;
562 1.56.10.2 ad
563 1.56.10.2 ad return (dkwedge_list(&ra->ra_disk, dkwl, l));
564 1.56.10.2 ad }
565 1.56.10.2 ad
566 1.56.10.2 ad default:
567 1.56.10.2 ad error = ENOTTY;
568 1.56.10.2 ad break;
569 1.56.10.2 ad }
570 1.56.10.2 ad return (error);
571 1.56.10.2 ad }
572 1.56.10.2 ad
573 1.56.10.2 ad
574 1.56.10.2 ad int
575 1.56.10.2 ad radump(dev, blkno, va, size)
576 1.56.10.2 ad dev_t dev;
577 1.56.10.2 ad daddr_t blkno;
578 1.56.10.2 ad void *va;
579 1.56.10.2 ad size_t size;
580 1.56.10.2 ad {
581 1.56.10.2 ad return ENXIO;
582 1.56.10.2 ad }
583 1.56.10.2 ad
584 1.56.10.2 ad /*
585 1.56.10.2 ad * Return the size of a partition, if known, or -1 if not.
586 1.56.10.2 ad */
587 1.56.10.2 ad int
588 1.56.10.2 ad rasize(dev)
589 1.56.10.2 ad dev_t dev;
590 1.56.10.2 ad {
591 1.56.10.2 ad int unit = DISKUNIT(dev);
592 1.56.10.2 ad struct ra_softc *ra;
593 1.56.10.2 ad
594 1.56.10.2 ad if (unit >= ra_cd.cd_ndevs || ra_cd.cd_devs[unit] == 0)
595 1.56.10.2 ad return -1;
596 1.56.10.2 ad
597 1.56.10.2 ad ra = ra_cd.cd_devs[unit];
598 1.56.10.2 ad
599 1.56.10.2 ad if (ra->ra_state == DK_CLOSED)
600 1.56.10.2 ad if (ra_putonline(ra) == MSCP_FAILED)
601 1.56.10.2 ad return -1;
602 1.56.10.2 ad
603 1.56.10.2 ad return ra->ra_disk.dk_label->d_partitions[DISKPART(dev)].p_size *
604 1.56.10.2 ad (ra->ra_disk.dk_label->d_secsize / DEV_BSIZE);
605 1.56.10.2 ad }
606 1.56.10.2 ad
607 1.56.10.2 ad #endif /* NRA */
608 1.56.10.2 ad
609 1.56.10.2 ad #if NRX
610 1.56.10.2 ad
611 1.56.10.2 ad int rxmatch(struct device *, struct cfdata *, void *);
612 1.56.10.2 ad
613 1.56.10.2 ad CFATTACH_DECL(rx, sizeof(struct rx_softc),
614 1.56.10.2 ad rxmatch, rxattach, NULL, NULL);
615 1.56.10.2 ad
616 1.56.10.2 ad dev_type_open(rxopen);
617 1.56.10.2 ad dev_type_read(rxread);
618 1.56.10.2 ad dev_type_write(rxwrite);
619 1.56.10.2 ad dev_type_ioctl(rxioctl);
620 1.56.10.2 ad dev_type_strategy(rxstrategy);
621 1.56.10.2 ad dev_type_dump(rxdump);
622 1.56.10.2 ad dev_type_size(rxsize);
623 1.56.10.2 ad
624 1.56.10.2 ad const struct bdevsw rx_bdevsw = {
625 1.56.10.2 ad rxopen, nullclose, rxstrategy, rxioctl, rxdump, rxsize, D_DISK
626 1.56.10.2 ad };
627 1.56.10.2 ad
628 1.56.10.2 ad const struct cdevsw rx_cdevsw = {
629 1.56.10.2 ad rxopen, nullclose, rxread, rxwrite, rxioctl,
630 1.56.10.2 ad nostop, notty, nopoll, nommap, nokqfilter, D_DISK
631 1.56.10.2 ad };
632 1.56.10.2 ad
633 1.56.10.2 ad static struct dkdriver rxdkdriver = {
634 1.56.10.2 ad rxstrategy, minphys
635 1.56.10.2 ad };
636 1.56.10.2 ad
637 1.56.10.2 ad /*
638 1.56.10.2 ad * More driver definitions, for generic MSCP code.
639 1.56.10.2 ad */
640 1.56.10.2 ad
641 1.56.10.2 ad int
642 1.56.10.2 ad rxmatch(parent, cf, aux)
643 1.56.10.2 ad struct device *parent;
644 1.56.10.2 ad struct cfdata *cf;
645 1.56.10.2 ad void *aux;
646 1.56.10.2 ad {
647 1.56.10.2 ad struct drive_attach_args *da = aux;
648 1.56.10.2 ad struct mscp *mp = da->da_mp;
649 1.56.10.2 ad
650 1.56.10.2 ad if ((da->da_typ & MSCPBUS_DISK) == 0)
651 1.56.10.2 ad return 0;
652 1.56.10.2 ad if (cf->cf_loc[MSCPBUSCF_DRIVE] != MSCPBUSCF_DRIVE_DEFAULT &&
653 1.56.10.2 ad cf->cf_loc[MSCPBUSCF_DRIVE] != mp->mscp_unit)
654 1.56.10.2 ad return 0;
655 1.56.10.2 ad /*
656 1.56.10.2 ad * Check if this disk is a floppy; then configure it.
657 1.56.10.2 ad * Seems to be a safe way to test it per Chris Torek.
658 1.56.10.2 ad */
659 1.56.10.2 ad if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
660 1.56.10.2 ad return 1;
661 1.56.10.2 ad return 0;
662 1.56.10.2 ad }
663 1.56.10.2 ad
664 1.56.10.2 ad #endif /* NRX */
665 1.56.10.2 ad
666 1.56.10.2 ad /*
667 1.56.10.2 ad * The attach routine only checks and prints drive type.
668 1.56.10.2 ad * Bringing the disk online is done when the disk is accessed
669 1.56.10.2 ad * the first time.
670 1.56.10.2 ad */
671 1.56.10.2 ad void
672 1.56.10.2 ad rxattach(parent, self, aux)
673 1.56.10.2 ad struct device *parent, *self;
674 1.56.10.2 ad void *aux;
675 1.56.10.2 ad {
676 1.56.10.2 ad struct rx_softc *rx = device_private(self);
677 1.56.10.2 ad struct drive_attach_args *da = aux;
678 1.56.10.2 ad struct mscp *mp = da->da_mp;
679 1.56.10.2 ad struct mscp_softc *mi = (void *)parent;
680 1.56.10.2 ad struct disklabel *dl;
681 1.56.10.2 ad
682 1.56.10.2 ad rx->ra_mediaid = mp->mscp_guse.guse_mediaid;
683 1.56.10.2 ad rx->ra_state = DK_CLOSED;
684 1.56.10.2 ad rx->ra_hwunit = mp->mscp_unit;
685 1.56.10.2 ad mi->mi_dp[mp->mscp_unit] = self;
686 1.56.10.2 ad
687 1.56.10.2 ad rx->ra_disk.dk_name = rx->ra_dev.dv_xname;
688 1.56.10.2 ad #if NRX
689 1.56.10.2 ad if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) == 'X' - '@')
690 1.56.10.2 ad rx->ra_disk.dk_driver = &rxdkdriver;
691 1.56.10.2 ad #endif
692 1.56.10.2 ad #if NRA
693 1.56.10.2 ad if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@')
694 1.56.10.2 ad rx->ra_disk.dk_driver = &radkdriver;
695 1.56.10.2 ad #endif
696 1.56.10.2 ad disk_attach((struct disk *)&rx->ra_disk);
697 1.56.10.2 ad
698 1.56.10.2 ad /* Fill in what we know. The actual size is gotten later */
699 1.56.10.2 ad dl = rx->ra_disk.dk_label;
700 1.56.10.2 ad
701 1.56.10.2 ad dl->d_secsize = DEV_BSIZE;
702 1.56.10.2 ad dl->d_nsectors = mp->mscp_guse.guse_nspt;
703 1.56.10.2 ad dl->d_ntracks = mp->mscp_guse.guse_ngpc * mp->mscp_guse.guse_group;
704 1.56.10.2 ad dl->d_secpercyl = dl->d_nsectors * dl->d_ntracks;
705 1.56.10.2 ad disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
706 1.56.10.2 ad #ifdef DEBUG
707 1.56.10.2 ad printf("%s: nspt %d group %d ngpc %d rct %d nrpt %d nrct %d\n",
708 1.56.10.2 ad self->dv_xname, mp->mscp_guse.guse_nspt, mp->mscp_guse.guse_group,
709 1.56.10.2 ad mp->mscp_guse.guse_ngpc, mp->mscp_guse.guse_rctsize,
710 1.56.10.2 ad mp->mscp_guse.guse_nrpt, mp->mscp_guse.guse_nrct);
711 1.56.10.2 ad #endif
712 1.56.10.2 ad if (MSCP_MID_ECH(1, mp->mscp_guse.guse_mediaid) != 'X' - '@') {
713 1.56.10.2 ad /*
714 1.56.10.2 ad * XXX We should try to discover wedges here, but
715 1.56.10.2 ad * XXX that would mean being able to do I/O. Should
716 1.56.10.2 ad * XXX use config_defer() here.
717 1.56.10.2 ad */
718 1.56.10.2 ad }
719 1.56.10.2 ad }
720 1.56.10.2 ad
721 1.56.10.2 ad /*
722 1.56.10.2 ad * (Try to) put the drive online. This is done the first time the
723 1.56.10.2 ad * drive is opened, or if it har fallen offline.
724 1.56.10.2 ad */
725 1.56.10.2 ad int
726 1.56.10.2 ad rx_putonline(rx)
727 1.56.10.2 ad struct rx_softc *rx;
728 1.56.10.2 ad {
729 1.56.10.2 ad struct mscp *mp;
730 1.56.10.2 ad struct mscp_softc *mi =
731 1.56.10.2 ad (struct mscp_softc *)device_parent(&rx->ra_dev);
732 1.56.10.2 ad volatile int i;
733 1.56.10.2 ad
734 1.56.10.2 ad rx->ra_state = DK_CLOSED;
735 1.56.10.2 ad mp = mscp_getcp(mi, MSCP_WAIT);
736 1.56.10.2 ad mp->mscp_opcode = M_OP_ONLINE;
737 1.56.10.2 ad mp->mscp_unit = rx->ra_hwunit;
738 1.56.10.2 ad mp->mscp_cmdref = 1;
739 1.56.10.2 ad *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
740 1.56.10.2 ad
741 1.56.10.2 ad /* Poll away */
742 1.56.10.2 ad i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
743 1.56.10.2 ad if (tsleep(&rx->ra_state, PRIBIO, "rxonline", 100*100))
744 1.56.10.2 ad rx->ra_state = DK_CLOSED;
745 1.56.10.2 ad
746 1.56.10.2 ad if (rx->ra_state == DK_CLOSED)
747 1.56.10.2 ad return MSCP_FAILED;
748 1.56.10.2 ad
749 1.56.10.2 ad return MSCP_DONE;
750 1.56.10.2 ad }
751 1.56.10.2 ad
752 1.56.10.2 ad #if NRX
753 1.56.10.2 ad
754 1.56.10.2 ad /*
755 1.56.10.2 ad * Open a drive.
756 1.56.10.2 ad */
757 1.56.10.2 ad /*ARGSUSED*/
758 1.56.10.2 ad int
759 1.56.10.2 ad rxopen(dev, flag, fmt, l)
760 1.56.10.2 ad dev_t dev;
761 1.56.10.2 ad int flag, fmt;
762 1.56.10.2 ad struct lwp *l;
763 1.56.10.2 ad {
764 1.56.10.2 ad struct rx_softc *rx;
765 1.56.10.2 ad int unit;
766 1.56.10.2 ad
767 1.56.10.2 ad /*
768 1.56.10.2 ad * Make sure this is a reasonable open request.
769 1.56.10.2 ad */
770 1.56.10.2 ad unit = DISKUNIT(dev);
771 1.56.10.2 ad if (unit >= rx_cd.cd_ndevs)
772 1.56.10.2 ad return ENXIO;
773 1.56.10.2 ad rx = rx_cd.cd_devs[unit];
774 1.56.10.2 ad if (rx == 0)
775 1.56.10.2 ad return ENXIO;
776 1.56.10.2 ad
777 1.56.10.2 ad /*
778 1.56.10.2 ad * If this is the first open; we must first try to put
779 1.56.10.2 ad * the disk online (and read the label).
780 1.56.10.2 ad */
781 1.56.10.2 ad if (rx->ra_state == DK_CLOSED)
782 1.56.10.2 ad if (rx_putonline(rx) == MSCP_FAILED)
783 1.56.10.2 ad return ENXIO;
784 1.56.10.2 ad
785 1.56.10.2 ad return 0;
786 1.56.10.2 ad }
787 1.56.10.2 ad
788 1.56.10.2 ad /*
789 1.56.10.2 ad * Queue a transfer request, and if possible, hand it to the controller.
790 1.56.10.2 ad *
791 1.56.10.2 ad * This routine is broken into two so that the internal version
792 1.56.10.2 ad * udastrat1() can be called by the (nonexistent, as yet) bad block
793 1.56.10.2 ad * revectoring routine.
794 1.56.10.2 ad */
795 1.56.10.2 ad void
796 1.56.10.2 ad rxstrategy(bp)
797 1.56.10.2 ad struct buf *bp;
798 1.56.10.2 ad {
799 1.56.10.2 ad int unit;
800 1.56.10.2 ad struct rx_softc *rx;
801 1.56.10.2 ad int b;
802 1.56.10.2 ad
803 1.56.10.2 ad /*
804 1.56.10.2 ad * Make sure this is a reasonable drive to use.
805 1.56.10.2 ad */
806 1.56.10.2 ad unit = DISKUNIT(bp->b_dev);
807 1.56.10.2 ad if (unit > rx_cd.cd_ndevs || (rx = rx_cd.cd_devs[unit]) == NULL) {
808 1.56.10.2 ad bp->b_error = ENXIO;
809 1.56.10.2 ad goto done;
810 1.56.10.2 ad }
811 1.56.10.2 ad
812 1.56.10.2 ad /* If disk is not online, try to put it online */
813 1.56.10.2 ad if (rx->ra_state == DK_CLOSED)
814 1.56.10.2 ad if (rx_putonline(rx) == MSCP_FAILED) {
815 1.56.10.2 ad bp->b_error = EIO;
816 1.56.10.2 ad goto done;
817 1.56.10.2 ad }
818 1.56.10.2 ad
819 1.56.10.2 ad /*
820 1.56.10.2 ad * Determine the size of the transfer, and make sure it is
821 1.56.10.2 ad * within the boundaries of the partition.
822 1.56.10.2 ad */
823 1.56.10.2 ad if (bp->b_blkno >= rx->ra_disk.dk_label->d_secperunit) {
824 1.56.10.2 ad bp->b_resid = bp->b_bcount;
825 1.56.10.2 ad goto done;
826 1.56.10.2 ad }
827 1.56.10.2 ad
828 1.56.10.2 ad /* Make some statistics... /bqt */
829 1.56.10.2 ad b = splbio();
830 1.56.10.2 ad disk_busy(&rx->ra_disk);
831 1.56.10.2 ad splx(b);
832 1.56.10.2 ad mscp_strategy(bp, device_parent(&rx->ra_dev));
833 1.56.10.2 ad return;
834 1.56.10.2 ad
835 1.56.10.2 ad done:
836 1.56.10.2 ad biodone(bp);
837 1.56.10.2 ad }
838 1.56.10.2 ad
839 1.56.10.2 ad int
840 1.56.10.2 ad rxread(dev, uio, flag)
841 1.56.10.2 ad dev_t dev;
842 1.56.10.2 ad struct uio *uio;
843 1.56.10.2 ad int flag;
844 1.56.10.2 ad {
845 1.56.10.2 ad
846 1.56.10.2 ad return (physio(rxstrategy, NULL, dev, B_READ, minphys, uio));
847 1.56.10.2 ad }
848 1.56.10.2 ad
849 1.56.10.2 ad int
850 1.56.10.2 ad rxwrite(dev, uio, flag)
851 1.56.10.2 ad dev_t dev;
852 1.56.10.2 ad struct uio *uio;
853 1.56.10.2 ad int flag;
854 1.56.10.2 ad {
855 1.56.10.2 ad
856 1.56.10.2 ad return (physio(rxstrategy, NULL, dev, B_WRITE, minphys, uio));
857 1.56.10.2 ad }
858 1.56.10.2 ad
859 1.56.10.2 ad /*
860 1.56.10.2 ad * I/O controls.
861 1.56.10.2 ad */
862 1.56.10.2 ad int
863 1.56.10.2 ad rxioctl(dev, cmd, data, flag, l)
864 1.56.10.2 ad dev_t dev;
865 1.56.10.2 ad u_long cmd;
866 1.56.10.2 ad void *data;
867 1.56.10.2 ad int flag;
868 1.56.10.2 ad struct lwp *l;
869 1.56.10.2 ad {
870 1.56.10.2 ad int unit = DISKUNIT(dev);
871 1.56.10.2 ad struct disklabel *lp;
872 1.56.10.2 ad struct rx_softc *rx = rx_cd.cd_devs[unit];
873 1.56.10.2 ad int error = 0;
874 1.56.10.2 ad
875 1.56.10.2 ad lp = rx->ra_disk.dk_label;
876 1.56.10.2 ad
877 1.56.10.2 ad switch (cmd) {
878 1.56.10.2 ad
879 1.56.10.2 ad case DIOCGDINFO:
880 1.56.10.2 ad bcopy(lp, data, sizeof (struct disklabel));
881 1.56.10.2 ad break;
882 1.56.10.2 ad
883 1.56.10.2 ad case DIOCGPART:
884 1.56.10.2 ad ((struct partinfo *)data)->disklab = lp;
885 1.56.10.2 ad ((struct partinfo *)data)->part =
886 1.56.10.2 ad &lp->d_partitions[DISKPART(dev)];
887 1.56.10.2 ad break;
888 1.56.10.2 ad
889 1.56.10.2 ad
890 1.56.10.2 ad case DIOCWDINFO:
891 1.56.10.2 ad case DIOCSDINFO:
892 1.56.10.2 ad case DIOCWLABEL:
893 1.56.10.2 ad break;
894 1.56.10.2 ad
895 1.56.10.2 ad default:
896 1.56.10.2 ad error = ENOTTY;
897 1.56.10.2 ad break;
898 1.56.10.2 ad }
899 1.56.10.2 ad return (error);
900 1.56.10.2 ad }
901 1.56.10.2 ad
902 1.56.10.2 ad int
903 1.56.10.2 ad rxdump(dev, blkno, va, size)
904 1.56.10.2 ad dev_t dev;
905 1.56.10.2 ad daddr_t blkno;
906 1.56.10.2 ad void *va;
907 1.56.10.2 ad size_t size;
908 1.56.10.2 ad {
909 1.56.10.2 ad
910 1.56.10.2 ad /* Not likely. */
911 1.56.10.2 ad return ENXIO;
912 1.56.10.2 ad }
913 1.56.10.2 ad
914 1.56.10.2 ad int
915 1.56.10.2 ad rxsize(dev)
916 1.56.10.2 ad dev_t dev;
917 1.56.10.2 ad {
918 1.56.10.2 ad
919 1.56.10.2 ad return -1;
920 1.56.10.2 ad }
921 1.56.10.2 ad
922 1.56.10.2 ad #endif /* NRX */
923 1.56.10.2 ad
924 1.56.10.2 ad void rrdgram(struct device *, struct mscp *, struct mscp_softc *);
925 1.56.10.2 ad void rriodone(struct device *, struct buf *);
926 1.56.10.2 ad int rronline(struct device *, struct mscp *);
927 1.56.10.2 ad int rrgotstatus(struct device *, struct mscp *);
928 1.56.10.2 ad void rrreplace(struct device *, struct mscp *);
929 1.56.10.2 ad int rrioerror(struct device *, struct mscp *, struct buf *);
930 1.56.10.2 ad void rrfillin(struct buf *, struct mscp *);
931 1.56.10.2 ad void rrbb(struct device *, struct mscp *, struct buf *);
932 1.56.10.2 ad
933 1.56.10.2 ad
934 1.56.10.2 ad struct mscp_device ra_device = {
935 1.56.10.2 ad rrdgram,
936 1.56.10.2 ad rriodone,
937 1.56.10.2 ad rronline,
938 1.56.10.2 ad rrgotstatus,
939 1.56.10.2 ad rrreplace,
940 1.56.10.2 ad rrioerror,
941 1.56.10.2 ad rrbb,
942 1.56.10.2 ad rrfillin,
943 1.56.10.2 ad };
944 1.56.10.2 ad
945 1.56.10.2 ad /*
946 1.56.10.2 ad * Handle an error datagram.
947 1.56.10.2 ad * This can come from an unconfigured drive as well.
948 1.56.10.2 ad */
949 1.56.10.2 ad void
950 1.56.10.2 ad rrdgram(usc, mp, mi)
951 1.56.10.2 ad struct device *usc;
952 1.56.10.2 ad struct mscp *mp;
953 1.56.10.2 ad struct mscp_softc *mi;
954 1.56.10.2 ad {
955 1.56.10.2 ad if (mscp_decodeerror(usc == NULL?"unconf disk" : usc->dv_xname, mp, mi))
956 1.56.10.2 ad return;
957 1.56.10.2 ad /*
958 1.56.10.2 ad * SDI status information bytes 10 and 11 are the microprocessor
959 1.56.10.2 ad * error code and front panel code respectively. These vary per
960 1.56.10.2 ad * drive type and are printed purely for field service information.
961 1.56.10.2 ad */
962 1.56.10.2 ad if (mp->mscp_format == M_FM_SDI)
963 1.56.10.2 ad printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",
964 1.56.10.2 ad mp->mscp_erd.erd_sdistat[10],
965 1.56.10.2 ad mp->mscp_erd.erd_sdistat[11]);
966 1.56.10.2 ad }
967 1.56.10.2 ad
968 1.56.10.2 ad void
969 1.56.10.2 ad rriodone(usc, bp)
970 1.56.10.2 ad struct device *usc;
971 1.56.10.2 ad struct buf *bp;
972 1.56.10.2 ad {
973 1.56.10.2 ad struct ra_softc *ra;
974 1.56.10.2 ad int unit;
975 1.56.10.2 ad
976 1.56.10.2 ad /* We assume that this is a reasonable drive. ra_strategy should
977 1.56.10.2 ad already have verified it. Thus, no checks here... /bqt */
978 1.56.10.2 ad unit = DISKUNIT(bp->b_dev);
979 1.56.10.2 ad #if NRA
980 1.56.10.2 ad if (cdevsw_lookup(bp->b_dev) == &ra_cdevsw)
981 1.56.10.2 ad ra = ra_cd.cd_devs[unit];
982 1.56.10.2 ad else
983 1.56.10.2 ad #endif
984 1.56.10.2 ad #if NRX
985 1.56.10.2 ad if (cdevsw_lookup(bp->b_dev) == &rx_cdevsw)
986 1.56.10.2 ad ra = rx_cd.cd_devs[unit];
987 1.56.10.2 ad else
988 1.56.10.2 ad #endif
989 1.56.10.2 ad panic("rriodone: unexpected major %d unit %d",
990 1.56.10.2 ad major(bp->b_dev), unit);
991 1.56.10.2 ad disk_unbusy(&ra->ra_disk, bp->b_bcount, (bp->b_flags & B_READ));
992 1.56.10.2 ad
993 1.56.10.2 ad biodone(bp);
994 1.56.10.2 ad }
995 1.56.10.2 ad
996 1.56.10.2 ad /*
997 1.56.10.2 ad * A drive came on line. Check its type and size. Return DONE if
998 1.56.10.2 ad * we think the drive is truly on line. In any case, awaken anyone
999 1.56.10.2 ad * sleeping on the drive on-line-ness.
1000 1.56.10.2 ad */
1001 1.56.10.2 ad int
1002 1.56.10.2 ad rronline(usc, mp)
1003 1.56.10.2 ad struct device *usc;
1004 1.56.10.2 ad struct mscp *mp;
1005 1.56.10.2 ad {
1006 1.56.10.2 ad struct rx_softc *rx = (struct rx_softc *)usc;
1007 1.56.10.2 ad struct disklabel *dl;
1008 1.56.10.2 ad
1009 1.56.10.2 ad wakeup((void *)&rx->ra_state);
1010 1.56.10.2 ad if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1011 1.56.10.2 ad printf("%s: attempt to bring on line failed: ", usc->dv_xname);
1012 1.56.10.2 ad mscp_printevent(mp);
1013 1.56.10.2 ad return (MSCP_FAILED);
1014 1.56.10.2 ad }
1015 1.56.10.2 ad
1016 1.56.10.2 ad rx->ra_state = DK_OPEN;
1017 1.56.10.2 ad
1018 1.56.10.2 ad dl = rx->ra_disk.dk_label;
1019 1.56.10.2 ad dl->d_secperunit = (daddr_t)mp->mscp_onle.onle_unitsize;
1020 1.56.10.2 ad
1021 1.56.10.2 ad if (dl->d_secpercyl) {
1022 1.56.10.2 ad dl->d_ncylinders = dl->d_secperunit/dl->d_secpercyl;
1023 1.56.10.2 ad dl->d_type = DTYPE_MSCP;
1024 1.56.10.2 ad dl->d_rpm = 3600;
1025 1.56.10.2 ad } else {
1026 1.56.10.2 ad dl->d_type = DTYPE_FLOPPY;
1027 1.56.10.2 ad dl->d_rpm = 300;
1028 1.56.10.2 ad }
1029 1.56.10.2 ad rrmakelabel(dl, rx->ra_mediaid);
1030 1.56.10.2 ad
1031 1.56.10.2 ad return (MSCP_DONE);
1032 1.56.10.2 ad }
1033 1.56.10.2 ad
1034 1.56.10.2 ad void
1035 1.56.10.2 ad rrmakelabel(dl, type)
1036 1.56.10.2 ad struct disklabel *dl;
1037 1.56.10.2 ad long type;
1038 1.56.10.2 ad {
1039 1.56.10.2 ad int n, p = 0;
1040 1.56.10.2 ad
1041 1.56.10.2 ad dl->d_bbsize = BBSIZE;
1042 1.56.10.2 ad dl->d_sbsize = SBLOCKSIZE;
1043 1.56.10.2 ad
1044 1.56.10.2 ad /* Create the disk name for disklabel. Phew... */
1045 1.56.10.2 ad dl->d_typename[p++] = MSCP_MID_CHAR(2, type);
1046 1.56.10.2 ad dl->d_typename[p++] = MSCP_MID_CHAR(1, type);
1047 1.56.10.2 ad if (MSCP_MID_ECH(0, type))
1048 1.56.10.2 ad dl->d_typename[p++] = MSCP_MID_CHAR(0, type);
1049 1.56.10.2 ad n = MSCP_MID_NUM(type);
1050 1.56.10.2 ad if (n > 99) {
1051 1.56.10.2 ad dl->d_typename[p++] = '1';
1052 1.56.10.2 ad n -= 100;
1053 1.56.10.2 ad }
1054 1.56.10.2 ad if (n > 9) {
1055 1.56.10.2 ad dl->d_typename[p++] = (n / 10) + '0';
1056 1.56.10.2 ad n %= 10;
1057 1.56.10.2 ad }
1058 1.56.10.2 ad dl->d_typename[p++] = n + '0';
1059 1.56.10.2 ad dl->d_typename[p] = 0;
1060 1.56.10.2 ad dl->d_npartitions = MAXPARTITIONS;
1061 1.56.10.2 ad dl->d_partitions[0].p_size = dl->d_partitions[2].p_size =
1062 1.56.10.2 ad dl->d_secperunit;
1063 1.56.10.2 ad dl->d_partitions[0].p_offset = dl->d_partitions[2].p_offset = 0;
1064 1.56.10.2 ad dl->d_interleave = dl->d_headswitch = 1;
1065 1.56.10.2 ad dl->d_magic = dl->d_magic2 = DISKMAGIC;
1066 1.56.10.2 ad dl->d_checksum = dkcksum(dl);
1067 1.56.10.2 ad }
1068 1.56.10.2 ad
1069 1.56.10.2 ad /*
1070 1.56.10.2 ad * We got some (configured) unit's status. Return DONE if it succeeded.
1071 1.56.10.2 ad */
1072 1.56.10.2 ad int
1073 1.56.10.2 ad rrgotstatus(usc, mp)
1074 1.56.10.2 ad struct device *usc;
1075 1.56.10.2 ad struct mscp *mp;
1076 1.56.10.2 ad {
1077 1.56.10.2 ad if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {
1078 1.56.10.2 ad printf("%s: attempt to get status failed: ", usc->dv_xname);
1079 1.56.10.2 ad mscp_printevent(mp);
1080 1.56.10.2 ad return (MSCP_FAILED);
1081 1.56.10.2 ad }
1082 1.56.10.2 ad /* record for (future) bad block forwarding and whatever else */
1083 1.56.10.2 ad #ifdef notyet
1084 1.56.10.2 ad uda_rasave(ui->ui_unit, mp, 1);
1085 1.56.10.2 ad #endif
1086 1.56.10.2 ad return (MSCP_DONE);
1087 1.56.10.2 ad }
1088 1.56.10.2 ad
1089 1.56.10.2 ad /*
1090 1.56.10.2 ad * A replace operation finished.
1091 1.56.10.2 ad */
1092 1.56.10.2 ad /*ARGSUSED*/
1093 1.56.10.2 ad void
1094 1.56.10.2 ad rrreplace(usc, mp)
1095 1.56.10.2 ad struct device *usc;
1096 1.56.10.2 ad struct mscp *mp;
1097 1.56.10.2 ad {
1098 1.56.10.2 ad
1099 1.56.10.2 ad panic("udareplace");
1100 1.56.10.2 ad }
1101 1.56.10.2 ad
1102 1.56.10.2 ad /*
1103 1.56.10.2 ad * A transfer failed. We get a chance to fix or restart it.
1104 1.56.10.2 ad * Need to write the bad block forwaring code first....
1105 1.56.10.2 ad */
1106 1.56.10.2 ad /*ARGSUSED*/
1107 1.56.10.2 ad int
1108 1.56.10.2 ad rrioerror(usc, mp, bp)
1109 1.56.10.2 ad struct device *usc;
1110 1.56.10.2 ad struct mscp *mp;
1111 1.56.10.2 ad struct buf *bp;
1112 1.56.10.2 ad {
1113 1.56.10.2 ad struct ra_softc *ra = (void *)usc;
1114 1.56.10.2 ad int code = mp->mscp_event;
1115 1.56.10.2 ad
1116 1.56.10.2 ad switch (code & M_ST_MASK) {
1117 1.56.10.2 ad /* The unit has fallen offline. Try to figure out why. */
1118 1.56.10.2 ad case M_ST_OFFLINE:
1119 1.56.10.2 ad bp->b_error = EIO;
1120 1.56.10.2 ad ra->ra_state = DK_CLOSED;
1121 1.56.10.2 ad if (code & M_OFFLINE_UNMOUNTED)
1122 1.56.10.2 ad printf("%s: not mounted/spun down\n", usc->dv_xname);
1123 1.56.10.2 ad if (code & M_OFFLINE_DUPLICATE)
1124 1.56.10.2 ad printf("%s: duplicate unit number!!!\n", usc->dv_xname);
1125 1.56.10.2 ad return MSCP_DONE;
1126 1.56.10.2 ad
1127 1.56.10.2 ad case M_ST_AVAILABLE:
1128 1.56.10.2 ad ra->ra_state = DK_CLOSED; /* Force another online */
1129 1.56.10.2 ad return MSCP_DONE;
1130 1.56.10.2 ad
1131 1.56.10.2 ad default:
1132 1.56.10.2 ad printf("%s:", usc->dv_xname);
1133 1.56.10.2 ad break;
1134 1.56.10.2 ad }
1135 1.56.10.2 ad return (MSCP_FAILED);
1136 1.56.10.2 ad }
1137 1.56.10.2 ad
1138 1.56.10.2 ad /*
1139 1.56.10.2 ad * Fill in disk addresses in a mscp packet waiting for transfer.
1140 1.56.10.2 ad */
1141 1.56.10.2 ad void
1142 1.56.10.2 ad rrfillin(bp, mp)
1143 1.56.10.2 ad struct buf *bp;
1144 1.56.10.2 ad struct mscp *mp;
1145 1.56.10.2 ad {
1146 1.56.10.2 ad struct rx_softc *rx = 0; /* Wall */
1147 1.56.10.2 ad struct disklabel *lp;
1148 1.56.10.2 ad int unit = DISKUNIT(bp->b_dev);
1149 1.56.10.2 ad int part = DISKPART(bp->b_dev);
1150 1.56.10.2 ad
1151 1.56.10.2 ad #if NRA
1152 1.56.10.2 ad if (cdevsw_lookup(bp->b_dev) == &ra_cdevsw)
1153 1.56.10.2 ad rx = ra_cd.cd_devs[unit];
1154 1.56.10.2 ad #endif
1155 1.56.10.2 ad #if NRX
1156 1.56.10.2 ad if (cdevsw_lookup(bp->b_dev) == &rx_cdevsw)
1157 1.56.10.2 ad rx = rx_cd.cd_devs[unit];
1158 1.56.10.2 ad #endif
1159 1.56.10.2 ad lp = rx->ra_disk.dk_label;
1160 1.56.10.2 ad
1161 1.56.10.2 ad mp->mscp_seq.seq_lbn = lp->d_partitions[part].p_offset + bp->b_blkno;
1162 1.56.10.2 ad mp->mscp_unit = rx->ra_hwunit;
1163 1.56.10.2 ad mp->mscp_seq.seq_bytecount = bp->b_bcount;
1164 1.56.10.2 ad }
1165 1.56.10.2 ad
1166 1.56.10.2 ad /*
1167 1.56.10.2 ad * A bad block related operation finished.
1168 1.56.10.2 ad */
1169 1.56.10.2 ad /*ARGSUSED*/
1170 1.56.10.2 ad void
1171 1.56.10.2 ad rrbb(usc, mp, bp)
1172 1.56.10.2 ad struct device *usc;
1173 1.56.10.2 ad struct mscp *mp;
1174 1.56.10.2 ad struct buf *bp;
1175 1.56.10.2 ad {
1176 1.56.10.2 ad
1177 1.56.10.2 ad panic("udabb");
1178 1.56.10.2 ad }
1179