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