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