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